画板类的代码:
package 画图板重绘;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
//画板类
public class Huaban {
Graphics g;
public static void main(String[] args){
Huaban hb = new Huaban();
hb.show();
}
private void show() {
JFrame jf = new JFrame();
jf.setTitle("画图板重绘");
jf.setSize(800, 800);
//设置居中显示
jf.setLocationRelativeTo(null);
jf.setLayout(new FlowLayout());
jf.setDefaultCloseOperation(3);
//在画布上创建鼠标监听器
Mouse m = new Mouse();
jf.addMouseListener(m);
//添加按钮
String[] text = {"直线","矩形"};
for(int i=0;i<text.length;i++)
{
JButton btn = new JButton(text[i]);
jf.add(btn);
btn.addActionListener(m);//给按钮添加动作监听器
}
jf.setVisible(true);
//获取画笔
Graphics g = jf.getGraphics();
//将画笔传到监听器去
m.g = g;
}
}
监听器代码:
package 画图板重绘;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Mouse implements MouseListener,ActionListener{
Graphics g;
String text = "";//按钮上的文字
int x1,x2,y1,y2;
//动作监听:当点击按钮的时候,获取按钮上的文字
public void actionPerformed(ActionEvent e){
text = e.getActionCommand();
}
public void mouseClicked(MouseEvent e){
}
//记录按下鼠标时点的坐标
public void mousePressed(MouseEvent e){
x1 = e.getX();
y1 = e.getY();
}
//记录鼠标释放时点的坐标,并根据按钮上的文字匹配画图方法
public void mouseReleased(MouseEvent e){
x2 = e.getX();
y2 = e.getY();
if("直线".equals(text))
{
g.drawLine(x1, y1, x2, y2);
}
if("矩形".equals(text))
{
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
}
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
}
如上代码实现的功能是在画图板界面上产生两个按钮:直线和矩形按钮。
当我们点击其中一个按钮的时候,用鼠标在界面上按住、释放,可以画出相应的直线和矩形。
效果如下:
但是当我们对窗口进行缩放的时候,我们原先画出的图会消失不见。这是因为当窗体在屏幕上显示的时候,首先是将窗体对象的数据从内存中取出来放到缓存中,再在屏幕上进行绘制。当窗体发生改变的时候,程序会重新从内存中获取更新后的数据进行绘制。我们画过的形状之所以会消失,就在于我们没有将画过的形状存放到内存中,所以当窗体发生重绘的时候就不会绘制了。
在系统中JFrame的父类中提供一个paint(Graphics g)的方法来负责将窗体数据在屏幕上绘制出来。
首先我们要将窗体类继承JFrame类,再重写JFrame类中的paint(Graphics g)方法:
package 画图板重绘;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Rejframe extends JFrame{
Shape[] s;
public void paint(Graphics g){
//一定要先调用父类的paint方法,用来绘制窗体
super.paint(g);
//写自己重绘的方法
for(int i=0;i<s.length;i++)
{
Shape shape = s[i];
if(shape!=null){
if("直线".equals(shape.type))
{
g.drawLine(shape.x1, shape.y1,shape.x2, shape.y2);
}
if("矩形".equals(shape.type))
{
g.drawRect(Math.min(shape.x1,shape.x2), Math.min(shape.y1, shape.y2), Math.abs(shape.x1-shape.x2), Math.abs(shape.y1-shape.y2));
}
}
}
}
}
我们需要在监听器中设置一个Shape(图形类)数组来记录画图需要的数据:
package 画图板重绘;
//图形类
public class Shape {
int x1,x2,y1,y2;
String type;
}
在监听器Mouse类中修改代码:
//创建图形类数组,每个单元存放一个图形
Shape[] s = new Shape[10];
//下标
int index=0;
public void mouseReleased(MouseEvent e){
x2 = e.getX();
y2 = e.getY();
if("直线".equals(text))
{
g.drawLine(x1, y1, x2, y2);
//创造shape类对象,将原图形的数据记录在缓存中
Shape h = new Shape();
h.x1 = x1;
h.x2 = x2;
h.y1 = y1;
h.y2 = y2;
h.type = "直线";
s[index++] = h;
}
if("矩形".equals(text))
{
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
//创造shape类对象,将原图形的数据记录在缓存中
Shape h = new Shape();
h.x1 = x1;
h.x2 = x2;
h.y1 = y1;
h.y2 = y2;
h.type = "矩形";
s[index++] = h;
}
}
还有一个重要的点是,我们重新构造的Rejframe类具有属性Shape[] s,在画板类代码中,我们需要修改JFrame jf = new JFrame(); 为Rejframe jf = new Rejframe();,同时还需要将监听器中的shape类数组传到画板中的shape类数组中去,jf.s = m.s;这样我们的窗体就可以找到需要重绘的数据。
这样实现之后,我们对窗体进行缩放,改变窗体大小都不会使我们已画好的图形消失。