现在我们已经可以开发一个画图板程序了。但细心一点会发现,当我们对画图板的窗体最小化或者改变大小的时候,我们先前用鼠标在窗体上画的东西就会全部没有了。
这是因为 窗体在屏幕上显示的时候,首先会将窗体对象的数据从内存中取出来放到缓存中,然后在屏幕上绘制,窗体改变的时候又会重新执行一遍这个步骤。我们画的形状并没有保存下来,窗体重绘是,自然就消失了。
要解决这个问题,只需要将我们用鼠标画的形状保存下来,并让窗体重绘时将我们画的形状也跟着重绘一遍即可。
1.创建Shape类保存画图所需数据
在我们画图过程中,需要保存的数据有点的坐标,需要画的是什么形状(是直线,矩形还是椭圆),另外还有颜色。Shape类代码如下:
2.继承JFrame类
我们要重写paint方法,首先要让界面类继承paint方法(paint方法在JFrame类里面)。代码如下:
import java.awt.Color;
import java.awt.Graphics;
public class Shape {
private int x1,x2,y1,y2;
private Color color;
private String name;
//重载构造方法
public Shape(){
}
public Shape(int x1,int y1,int x2,int y2,Color color,String name){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color=color;
this.name = name;
}
public void SetShape(int x1,int y1,int x2,int y2,Color color,String name){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
this.name = name;
}
//重绘时所需的方法
public void DrawShape(Graphics g){
switch(name){
case "直线":
g.drawLine(x1, y1, x2, y2);g.setColor(color);
break;
case "矩形":
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
g.setColor(color);
break;
case "椭圆":
g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
g.setColor(color);
break;
}
}
}
2.创建Shape数组保存数据
我们用鼠标在画图板上画图形时,每画一次,监听器里面的数据就会被赋值一次,所以我们可以在监听器里面创建数组保存画图所需数据,代码如下:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
public class FrameListener implements MouseListener, ActionListener {
private Graphics g;
private Color color;//定义颜色属性
private String name;//接受按钮上的文字
private int x1,y1,x2,y2;
public Shape[] array = new Shape[100]; //创建Shape数组保存所需数据
private int index=0;//操作数组的下标
public void setGr(Graphics g){
this.g = g; // 传输画笔对象
}
public Shape[] getShape(){
return array;//方便重写paint方法获得数组
}
// 操作添加ActionListener的对象时调用此方法
public void actionPerformed(ActionEvent e) {
//操作按钮时获取按钮信息,并对是文字还是颜色进行分类
if(e.getActionCommand().equals("")){
JButton jbuc=(JButton)e.getSource();
//可以获得JButton的所有信息,e.getSource();可以获取所有组件信息string name2=e.getText。
color = jbuc.getBackground();
}
else{
name = e.getActionCommand();//如果按钮上有文字,获取文字,用name变量保存
}
}
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();//获取释放时候点的坐标
g.setColor(color);//可以通过对按钮执行按压操作改变画笔的颜色
// 创建图形对象
Shape shape = new Shape();
if("直线".equals(name))
g.drawLine(x1, y1, x2, y2);//画直线
shape.SetShape(x1, y1, x2, y2, color, name);
// 调用构造方法将数据保存到数组中
array[index++] = shape;
if("矩形".equals(name))
g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
shape.SetShape(x1, y1, x2, y2, color, name);
// 调用构造方法将数据保存到数组中
array[index++] = shape;
if("椭圆".equals(name))
g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
shape.SetShape(x1, y1, x2, y2, color, name);
// 调用构造方法将数据保存到数组中
array[index++] = shape;
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
3.重写paint方法
要重写paint方法,首先我们要让界面类继承JFrame,(paint方法在JFrame类中)。代码如下:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
public class DrawFrame extends JFrame {
private static final long serialVersionUID = 1L;
public Shape [] shapeArray = new Shape[100];
public static void main(String []args){
DrawFrame df = new DrawFrame();
df.Frame();
}
public void Frame(){
this.setTitle("画板");
this.setSize(700,800);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
this.getContentPane().setBackground(Color.white);
FlowLayout layout = new FlowLayout(FlowLayout.CENTER, 40, 10);
this.setLayout(layout);
FrameListener fl = new FrameListener();//创建监听器对象
String btname [] = {"直线","矩形","椭圆"};
for(int i=0;i<btname.length;++i){
JButton jbu = new JButton(btname[i]);
jbu.setPreferredSize(new Dimension(60,30));
jbu.addActionListener(fl);
this.add(jbu);
}
String colorname[] = {"红色","黑色","蓝色"};
Color [] color = {Color.red,Color.black,Color.blue};
for(int j=0;j<colorname.length;++j){
JButton jbu = new JButton();
jbu.setBackground(color[j]);
jbu.setPreferredSize(new Dimension(60,30));
jbu.addActionListener(fl);
this.add(jbu);
}
this.setVisible(true);
//画笔:图形画在那个组件上,画笔就从改组件上获取
//从窗体上获取画笔对象,一定要在窗体显示可见之后
Graphics g = this.getGraphics();
this.addMouseListener(fl);//给窗体添加监听器方法
fl.setGr(g);//将画笔对象传到监听器
shapeArray=fl.getShape();
}
// 重写paint方法
public void paint(Graphics g){
super.paint(g); //调用父类中被子类隐藏的方法,此步很重要,如果没有,界面也不会重绘
for(int i=0;i<100;i++){
Shape shape = shapeArray[i];
if(shape != null){
shape.DrawShape(g);
}else{
break;
}
}
}
}
通过这三步,就能完成画图板的重绘。