* 最简单实现拖动鼠标画圆功能(可以推广画其它图形),目的: * 1、锻炼Graphics对象画图,画到什么地方, * 2、实现拖动鼠标画图时显示轨迹效果; * 3、锻炼repaint()与paint()方法应用. * 4、实现双缓冲效果. */
import java.awt.Color; import java.awt.Graphics; import java.awt.Image;
import java.awt.event.MouseEvent; import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener; import java.awt.image.BufferedImage;
import javax.swing.JFrame; import javax.swing.JPanel;
public class TestDrawFrame extends JFrame {
private static final long serialVersionUID = 1L;
// 内部类对象,用于画图的面板,实现MouseListener和MouseMotionListener接口 pane p = null;
// 按下鼠标时的X、Y坐标 int pressX; int pressY;
// 用于画图的缓冲区图片
private Image image = new BufferedImage(300, 400, BufferedImage.TYPE_INT_BGR);
// 初始化窗体
public void init() {
// 从缓冲区图片获得Graphics对象,每次注意g是哪里来的 Graphics g = image.getGraphics(); // 将缓冲区图片用白色填充背景,目的是那在上面画时好呈现各种颜色,用其它颜色作背景
// 不是不可以,但不多(习惯)。 g.setColor(Color.white); g.fillRect(0, 0, 300, 400); // 初始化面板,并添加鼠标事件 p = new pane();
p.setBackground(Color.white); p.addMouseListener(p);
p.addMouseMotionListener(p);
// 添加面板到窗体中去,并设置窗体大小,可见等 this.add(p);
this.setSize(300, 400); this.setVisible(true); }
public static void main(String[] args) {
TestDrawFrame frame = new TestDrawFrame(); frame.init(); }
/*
* 内部类,用于实现画图的面板 */
class pane extends JPanel implements MouseListener, MouseMotionListener {
private static final long serialVersionUID = 1L;
/*
* 此处要注意几点: 一:paint()方法是哪个的,可以把该代码放到外面frame中试度,因为frame
* 也有该方法,但这样一来,刷新的是frame,而不是画板;因此每次刷新时 * 面板中的paint()方法中的代码不会被执行,因此效果也没了,放到外面试试! * 二:如果把该方法注掉,然后再把窗口最大化或最小化一次(让窗口刷新), * 图片没了,那是因为每次刷新都要将缓冲区中的图片往屏幕(实际是面板,注意 这个g是从那里来的)上画一次,感觉就是没变化,还是刚才的图,试试。 */
public void paint(Graphics g) { g.drawImage(image, 0, 0, null); }
public void mousePressed(MouseEvent e) {
pressX = e.getX(); pressY = e.getY(); }
public void mouseReleased(MouseEvent e) { /*
* 此处的Graphics对象是缓冲区图片对象提供,将图画到缓冲区,要注意与下面Draw()方法
* 中的Graphics区别,(Graphics提供对象不同,画的地方不同),显示调用repaint()方法,
* 是执行pane对象的paint()方法,目的是把缓冲区的图片画到屏幕上(实
际是面板上) */
Graphics g = image.getGraphics(); g.setColor(Color.red);
int x = e.getX() > pressX ? pressX : e.getX(); int y = e.getY() > pressY ? pressY : e.getY();
g.drawOval(x, y, Math.abs(pressX - e.getX()), Math.abs(pressY - e.getY())); }
public void draw(MouseEvent e) {
/*
* 此处的Graphics对象是由画图面板Pane提供,因此画的时候只显示在面板上(显示轨迹),并不能真正
* 写到缓冲区图片上,该事件重新执行时会被第二句:g.drawImage(image, 0, 0, null);覆盖,实际
* 就成了什么都没做。于是会出现刚才画的东东一下不见了,可以将MouseReleased中的代码注
* 掉试试试!真正画图到缓冲区的代码放在了MouseReleased中,而真正将图片画到屏幕是 paint()方法中. */
Graphics g = p.getGraphics();
// 此处也很重要,如果没有此句,出现的就是很多个圆的重叠,因为没有用 // 缓冲区的图片来擦去每次拖动产生的圆,可以将该句代码注掉试试。 g.drawImage(image, 0, 0, null);
int x = e.getX() > pressX ? pressX : e.getX(); int y = e.getY() > pressY ? pressY : e.getY(); g.setColor(Color.red);
g.drawOval(x, y, Math.abs(pressX - e.getX()), Math.abs(pressY - e.getY())); }
// 以事件不关心,因此不用实现
public void mouseClicked(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
}
public void mouseDragged(MouseEvent e) { draw(e); }
public void mouseMoved(MouseEvent e) { } }
因篇幅问题不能全部显示,请点此查看更多更全内容