在使用Java进行画图工具编写时,我们会遇到图形重绘问题。当我们改变窗体的状态(隐藏,改变大小)时,窗体上所有的组件会进行重绘,但我们自己绘制的图形却不再显示,因此我们需要对这些图形进行重绘。
1.图形的封装
要想实现图形重绘,我们首先得保存图形的对应数据。例如对于线段,我们需要保存它的图形名称、两个端点、颜色等。因此我们定义一个Shapes类用于封装图形数据,并在Shapes类中用构造方法(每个类都有一个默认的无参构造方法,当自己定义构造方法,那么默认的无参构造方法就会被替代)同时给它的多个属性赋值。
public class Shapes {
//属性
public int x1,y1,x2,y2;
public String name;
//构造方法 格式:public 类名(参数类型 参数名,,){ 方法体..}
public Shapes(int x1,int y1,int x2,int y2,String name){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.name = name;
}
}
之后我们便可以给Shaps类添加drawshape方法用将封装数据转换为图形。
public class Shapes {
//属性
public int x1,y1,x2,y2;
public String name;
//构造方法 格式:public 类名(参数类型 参数名,,){ 方法体..}
public Shapes(int x1,int y1,int x2,int y2,String name){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.name = name;
}
public void drawShape(Graphics g){
switch (name){
case "直线":
g.drawLine(x1,y1,x2,y2);
break;
}
}
}
这样我们便搭建好了Shapes类的基本框架,实现了图形封装功能。
2.图形数据的获取与保存
在拥有图形封装功能之后,我们便能便捷地对图形数据进行获取与保存。以直线为例,数据的获取应在直线绘制完成,即鼠标监听器识别到“松开”时进行。由于需要重绘的图形一般有多个,所以我们需要定义一个Shapes类的数组shapeArr去依次存储图形。设置数组下标为index。
public void mouseReleased(MouseEvent e) {
if ("直线".equals(name)) {
//绘制图形
g.drawLine(x1, y1, x2, y2);
//创建Shapes对象保存数据
Shapes shape = new Shapes(x1,y1,x2,y2,name);
shapeArr[index++] = shape;
}
}
3.组件paint方法的重写
我们改变窗体的状态时组件之所以能重绘,是因为所有的组件都有一个paint方法用于绘制组件本身。因此要实现图形重绘,第二步是找到显示图形的组件,并新建子类继承它来重写其paint方法。例如当我们的图形显示在画图面板上时,我们用MPanel类去继承JPanel类,即创建一个自定义面板。
在paint方法中我们需要完成两个任务:一是保留JPanel原本的重绘组件功能,二是加入图形重绘功能,遍历shapeArr数组并调用drawshape方法。
public class MPanel extends JPanel {
private Shapes[] shapeArr;
//定义set 设置属性
public void setShapeArr(Shapes[] shapeArr) {
this.shapeArr = shapeArr;
}
//重写paint方法
public void paint(Graphics g) {
//1.保留绘制组件的功能:调用父类方法
//super 表示当前类的父类对象
super.paint(g);
//2.绘制图形
for (int i = 0; i < shapeArr.length; i++) {
Shapes shape = shapeArr[i];
if (shape == null) break;
shape.drawShape(g);
}
}
}
完成方法重写后,我们只需将显示画图工具的方法中将JPanel修改为MPanel,调用setShapeArr方法把shapeArr数组从DrawListener类传递给MPanel类即可。之后我们再改变窗体状态,新的paint方法生效,绘制的图形就不会消失了。
如此我们便实现了基础的图形重绘功能。