Cách vẽ trên JPanel trong Java Swing

Hi there ! cho em hỏi trong 1 frame có panel A, B, C mà mình chỉ muốn vẽ lên panel A thôi, không liên quan gì đến panel B, C thì làm như nào nhỉ ?
dùng chuột vẽ lên panel kiểu như microsoft paint ạ !

Thì bắt sự kiện chuột/phím và vẽ lên nó thôi.
Ghi đè phương thức paint(Graphics) của JPanel.
Google có hàng triệu ví dụ: Java paint graphics
Nếu vẽ theo vị trí chuột thì bạn cần đến: drawPolygons() hoặc drawLine()
Xem hướng dẫn 3 cách vẽ: https://www.geeksforgeeks.org/draw-polygon-java-applet/

Applet với JFrame giống nhau thôi.

3 Likes

anh ơi, em thử paintComponent(), paint(), nó đều hiện các component trên panel khác lên panel khu vực vẽ ạ. giúp e fix với

Mã bạn viết thế nào, có thể bạn vô tình gọi lại phương thức của lớp cha, làm cho nó vẽ lại.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JPanel;

public class PanelArea extends JPanel {
	private Point point = new Point();

	public PanelArea() {
		addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseDragged(MouseEvent event) {
				point = event.getPoint();
				repaint();
			}
		});

	}

	protected void paintComponent(Graphics g) {
		g.setColor(PaintApp.color);
		if (PaintApp.rdoOval.isSelected()) {
			if (PaintApp.rdoFill.isSelected()) {
				g.fillOval(point.x, point.y, 20, 20);
			}
			if (PaintApp.rdoOutLine.isSelected()) {
				g.drawOval(point.x, point.y, 20, 20);
			}
		}
		if (PaintApp.rdoSquare.isSelected()) {
			if (PaintApp.rdoFill.isSelected()) {
				g.fillRect(point.x, point.y, 20, 20);
			}
			if (PaintApp.rdoOutLine.isSelected()) {
				g.drawRect(point.x, point.y, 20, 20);
			}
		}
	}

}
import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

public class PaintApp extends JFrame implements ActionListener {
	private Point point = new Point();

public static JButton btnRed, btnBlue, btnClear;
public static JRadioButton rdoSquare, rdoOval, rdoFill, rdoOutLine;

public static Color color;

public PaintApp() {
	addComponet();
	eventHandling();
	display();
}

private void eventHandling() {
	btnBlue.addActionListener(this);
	btnRed.addActionListener(this);
	rdoOval.addActionListener(this);
	rdoSquare.addActionListener(this);
	rdoFill.addActionListener(this);
	rdoOutLine.addActionListener(this);

}

private void addComponet() {
	setLayout(new BorderLayout());
	JPanel pnOption = new JPanel();
	pnOption.setBackground(Color.pink);
	add(pnOption, BorderLayout.NORTH);
	pnOption.add(btnRed = new JButton());
	pnOption.add(btnBlue = new JButton());
	btnRed.setBackground(Color.RED);
	btnBlue.setBackground(Color.BLUE);
	pnOption.add(rdoSquare = new JRadioButton("Square"));
	pnOption.add(rdoOval = new JRadioButton("Oval"));
	pnOption.add(rdoFill = new JRadioButton("Fill"));
	pnOption.add(rdoOutLine = new JRadioButton("Out Line"));
	rdoOutLine.setSelected(true);
	rdoSquare.setSelected(true);
	ButtonGroup btnGroup = new ButtonGroup();
	btnGroup.add(rdoOval);
	btnGroup.add(rdoSquare);
	ButtonGroup btnGroup2 = new ButtonGroup();
	btnGroup2.add(rdoFill);
	btnGroup2.add(rdoOutLine);
	
	JPanel pnOption2 = new JPanel();
	add(pnOption2, BorderLayout.WEST);
	pnOption2.setBackground(Color.PINK);
	pnOption2.add(btnClear= new JButton("Clear all"));
	

	PanelArea pnPaintArea = new PanelArea();
	add(pnPaintArea, BorderLayout.CENTER);
	pnPaintArea.setBackground(Color.CYAN);
}

public void actionPerformed(ActionEvent e) {
	if (e.getSource() == btnBlue) {
		color = Color.BLUE;
	}
	if (e.getSource() == btnRed) {
		color = Color.RED;
	}
}

private void display() {
	setSize(650, 600);
	setDefaultCloseOperation(EXIT_ON_CLOSE);
	setLocationRelativeTo(null);
	setVisible(true);
}

public static void main(String[] args) {
	new PaintApp();
}

}

em nghĩ là do cái phương thức paintComponent(), không biết là do sử dụng sai hay là do em đặt sai chỗ. anh xem giúp em với. cảm ơn a nhiều !

Cơ bản là do bạn chưa xóa trước khi vẽ.

Có lẽ Java dùng chung 1 đối tượng Graphics cho việc vẽ tất cả các thành phần riêng biệt. Vì thế mà các nội dung được vẽ ra trước đó vẫn còn sót lại.

Cách thức làm của bạn là cứ vẽ chồng lên nhiều lần. Cách này không ổn, sẽ gây hiện tượng như vậy.
Bạn phải gọi phương thức clearRect(). Sau đó vẽ lại toàn bộ. Đó cách thức vẽ đồ họa cơ bản.
Điều này có nghĩa là bạn phải lưu lại mọi thao tác trước đó như tọa độ nhấn chuột, màu sắc và hình dạng. Windows Paint mới.

Nhưng có cách nhanh chóng hơn là dùng bộ đệm. Bạn vẽ vào một đối tượng đồ họa riêng (Image), sau đó vẽ cả đối tượng đó lên đối tượng Graphics trong phương thức paint(). Windows Paint cũ.
Còn 1 thứ có liên quan là Double Buffer giúp quá trình vẽ và cập nhật được ổn định hơn.
Bạn nên vẽ vào BufferImage trước, sau đó vẽ nó lên Graphics2D (ép kiểu từ Graphics) trong paint() thông qua phương thức Graphics2D.drawImage().

Mong bạn tự tìm hiểu và thành công.

4 Likes
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JComponent;

public class DrawArea extends JComponent {

	private Image image;
	private Graphics graphic;
	private Point point;

	public DrawArea() {
		addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseDragged(MouseEvent e) {
				point = e.getPoint();
				repaint();
			}
		});
	}

	protected void paintComponent(Graphics g) {
		if (graphic != null) {
			graphic.drawRect(point.x, point.y, 20, 20);
		}
		if (image == null) {
			image = createImage(getSize().width, getSize().height);
			graphic = image.getGraphics();
		}
		g.drawImage(image, 0, 0, null);
	}
}
1 Like

Em làm được rồi, cảm ơn anh đã giúp ! :heart_eyes:

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?