关于图形重绘(链接画图工具)
图形重绘
1.所有的swing组件都有一个paint方法,绘制组件本身;
2. 当改变窗体的状态(隐藏,改变大小)都会导致窗体上所有的组件重新调用paint方法(组件重绘),若没有编写重绘代码,会导致所绘画内容清空;
3. 想要完成图形重绘,需要两步:
一,保存图形的数据:根据图形对象设计对应的类;
二,继承绘制图形的面板,重写该面板类的paint方法。
(完成图形重绘涉及四个Java class)
在第一个Java class中------------------------------------------------------------
仅需要在原有基础上添加两步:
1.自定义面板MPanel:
MPanel drawPanel = new MPanel();
(MPanel继承JPanel,在 MPanel(第四个Java class) 中添加自定义的功能)
2.传递:
//把DrawListener类中的shapeArr数组传递给MPanel类
drawPanel.shapeArr = listener.shapeArr;
完整示例:
import javax.swing.*;
import java.awt.*;
import java.awt.Graphics;
/**
* @author chen
* @date 2025/7/13 19:22
* @description
*
*/
public class DrawUI {
//显示画图工具的界面
public void initUI(){
JFrame jf = new JFrame();
jf.setSize(900,900);
jf.setTitle("画图工具");
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(3);
JPanel northPanel = new JPanel();
northPanel.setPreferredSize(new Dimension(0,40));
northPanel.setBackground(Color.GREEN);
jf.add(northPanel,BorderLayout.NORTH);
DrawListener listener = new DrawListener();//在数组前创建对象listener
String[] name = {"直线", "矩形","任意三角形", "多边形", "曲线","橡皮擦", "红色", "蓝色", "黑色","粗","细"};
for (int i = 0; i < name.length; i++) {
JButton jbu = new JButton(name[i]);
northPanel.add(jbu);
jbu.addActionListener(listener);
}
MPanel drawPanel = new MPanel();
drawPanel.setBackground(Color.WHITE);
jf.add(drawPanel,BorderLayout.CENTER);
jf.setVisible(true);//
//画笔:图形内容显示在哪个组件上,画笔就从该组件上获取
//从窗体上获取画笔对象:一定要在窗体可见之后
Graphics g = drawPanel.getGraphics();
//给窗体添加鼠标监听器方法
drawPanel.addMouseListener(listener);
drawPanel.addMouseMotionListener(listener);
//把画笔对象g 传递给DrawListener类
listener.gr = g;
drawPanel.shapeArr = listener.shapeArr;
}
public static void main(String[] args){
DrawUI ui = new DrawUI();
ui.initUI();
}
}
在第二个Java class中------------------------------------------------------------
1.定义所需要的属性:如颜色,粗细,数组等;
//定义Shapes数组保存图形对象
public Shapes[] shapeArr = new Shapes[2000];
//操作数组的下标
public int index = 0;
public Color color = Color.BLACK;
public float lineWidth = 1.0f;
(注意这里的颜色和粗细都需要单独用定义变量,以便于后续保存)
(2000,是数组保存对象数量,由于涉及曲线和橡皮擦这样需要大量保存的工具,故数字要设置的大一点)
2.颜色和粗细的控制如下:
public void actionPerformed(ActionEvent e) {
//获取按钮上的内容
String str = e.getActionCommand();;
if("蓝色".equals(str)){
color = Color.BLUE;
}else if("红色".equals(str)){
color = Color.RED;
}else if("黑色".equals(str)) {
color = Color.BLACK;
}else if("粗".equals(str)){
lineWidth = 5;
Graphics2D g2 = (Graphics2D)gr;
BasicStroke stroke = new BasicStroke(lineWidth);
g2.setStroke(stroke);
}else if("细".equals(str)){
lineWidth = 1;
Graphics2D g2 = (Graphics2D)gr;
BasicStroke stroke = new BasicStroke(lineWidth);
g2.setStroke(stroke);
}else{
name = e.getActionCommand();
}
gr.setColor(color);
System.out.println("点击按钮!name = " + name);
}
(注意粗细和原来没有用变量单独保存时的变化)
3.对于保存数据,可看作将需要的点的坐标的保存,再在第三个Java class中重绘,方法视所需决定,一般以以下格式:
Shapes shape = new Shapes(name,color,lineWidth,x1,y1,x2,y2,x3,y3);
shapeArr[index] = shape;
index++;
(可将颜色粗细一并保存并重绘)
(小括号里的保存内容和数量与第三个java class方法中的数据一一对应)
4.完整示例:
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.*;
/**
* @author chen
* @date 2025/7/13 19:29
* @description 实现接口:public class 子类 implements 接口,接口,,,{}
* 实现接口一定要重写接口中所有的抽象方法
*/
public class DrawListener implements MouseListener, ActionListener, MouseMotionListener {
//引用传递
public Graphics gr;
//全局变量:属性
public int x1,y1,x2,y2,x3,y3,x4,y4;
public String name;
public Color color = Color.BLACK;
public float lineWidth = 1.0f;
//设置标记位,控制代码执行顺序
public int flag = 1;
public Shapes[] shapeArr = new Shapes[2000];
//操作数组的下标
public int index = 0;
//动作监听器处理方法
public void actionPerformed(ActionEvent e) {
//获取按钮上的内容
String str = e.getActionCommand();;
if("蓝色".equals(str)){
color = Color.BLUE;
}else if("红色".equals(str)){
color = Color.RED;
}else if("黑色".equals(str)) {
color = Color.BLACK;
}else if("粗".equals(str)){
lineWidth = 5;
Graphics2D g2 = (Graphics2D)gr;
BasicStroke stroke = new BasicStroke(lineWidth);
g2.setStroke(stroke);
}else if("细".equals(str)){
lineWidth = 1;
Graphics2D g2 = (Graphics2D)gr;
BasicStroke stroke = new BasicStroke(lineWidth);
g2.setStroke(stroke);
}else{
name = e.getActionCommand();
}
gr.setColor(color);
System.out.println("点击按钮!name = " + name);
}
//鼠标监听器处理方法
public void mouseClicked(MouseEvent e) {
x3 = e.getX();
y3 = e.getY();
if("任意三角形".equals(name)){
Shapes shape = new Shapes(name,color,lineWidth,x1,y1,x2,y2,x3,y3);
shapeArr[index] = shape;
index++;
gr.drawLine(x1,y1,x3,y3);
gr.drawLine(x2,y2,x3,y3);
flag=1;
System.out.println("x3 = "+x3+" y3 = "+y3);
}
if("多边形".equals(name)){
Shapes shape = new Shapes(name,color,lineWidth,x3,y3,x2,y2);
shapeArr[index] = shape;
index++;
gr.drawLine(x2,y2,x3,y3);
//让当前线段的终点变成下条线段的起点
x2 = x3;
y2 = y3;
//判断是否双击: e.getClickCount() == 2
if( e.getClickCount() == 2){
gr.drawLine(x1,y1,x3,y3);
flag = 1;
shape = new Shapes(name,color,lineWidth,x1, y1, x3, y3);
shapeArr[index] = shape;
index++;
}
}
}
public void mousePressed(MouseEvent e) {
System.out.println("按下");
//获取当前坐标值
//作用域:一对大括号就是一个独立作用域
//局部变量:1.在方法(作用域)中定义的变量 2.方法的参数
if(flag == 1) {
x1 = e.getX();
y1 = e.getY();
}
System.out.println("x1 = "+x1+" y1 = "+y1);
}
public void mouseReleased(MouseEvent e) {
System.out.println("松开");
if(flag == 1) {
x2 = e.getX();
y2 = e.getY();
}
System.out.println("x2 = "+x2+" y2 = "+y2);
//绝对值
int w = Math.abs(x2 - x1);
int u = Math.abs(y2 - y1);
int mx = Math.min(x1, x2);
int my = Math.min(y1, y2);
if ("直线".equals(name)) {
//只需要在松开鼠标后保存数据
//创建Shapes对象,把绘制直线的数据保存到对象中
Shapes shape = new Shapes(name,color,lineWidth,x1,y1,x2,y2);
shapeArr[index] = shape;
index++;
}
if ("矩形".equals(name)) {
//矩形
Shapes shape = new Shapes(name,color,lineWidth,mx,my,w,u);
shapeArr[index] = shape;
index++;
gr.drawRect(mx, my, w, u);
}
if("任意三角形".equals(name) ){
gr.drawLine(x1, y1, x2, y2);
flag++;
}
if("多边形".equals(name) && flag == 1){
gr.drawLine(x1, y1, x2, y2);
flag++;
Shapes shape = new Shapes(name,color,lineWidth,x1,y1,x2,y2);
shapeArr[index] = shape;
index++;
}
if ("橡皮擦".equals(name)) {
Graphics2D g2 = (Graphics2D) gr;
BasicStroke stroke = new BasicStroke(1);
g2.setStroke(stroke);
gr.setColor(color);
}
}
public void mouseDragged(MouseEvent e){
if ("直线".equals(name)) {
//绘制图形
gr.setColor(Color.WHITE);
gr.drawLine(x1, y1, x4, y4);
x4 = e.getX();
y4 = e.getY();
gr.setColor(color);
gr.drawLine(x1, y1, x4, y4);
}
if("曲线".equals(name)){
x4 = e.getX();
y4 = e.getY();
Shapes shape = new Shapes(name,color,lineWidth,x1,y1,x4,y4);
shapeArr[index] = shape;
index++;
gr.drawLine(x1,y1,x4,y4);
x1=x4;
y1=y4;
}
if("橡皮擦".equals(name)){
x4 = e.getX();
y4 = e.getY();
Shapes shape = new Shapes(name,color,lineWidth,x1,y1,x4,y4);
shapeArr[index] = shape;
index++;
Graphics2D g2 = (Graphics2D) gr;
g2.setStroke(new BasicStroke(5));
gr.setColor(Color.WHITE);
gr.drawLine(x1, y1, x4, y4);
x1 = x4;
y1 = y4;
}
}
public void mouseMoved(MouseEvent e){
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
在第三个Java class中------------------------------------------------------------
1.调用方法:
public class Shapes{}
2.定义所需使用的属性:
public int x1,y1,x2,y2,x3,y3;
public String name="";
public Color color ;
public float lineWidth;
(注意这里使name为空字符串,是为了避免空指针异常NullPointerException报错)
3.在第二个java class中Shapes shape = new Shapes();
【每个类都有一个默认的无参构造方法,当自己定义构造方法,那么默认的无参构造方法就会被替代】
故想简化保存数据的步骤,可通过自定义构造方法的方式实现:
public Shapes(String name,Color color,float lineWidth,int x1,int y1,int x2,int y2,int x3,int y3){
this.name = name;
this.color = color;
this.lineWidth = lineWidth;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
}
(this 表示本类对象,super 表示当前类的父类对象)
方法重载(区别于方法重写)
方法重载:同一个方法通过参数选择实现不同的功能
使用条件:1.方法名重名 2.参数类型(个数,顺序)不一样
拓展
方法 格式:public 返回值类型 方法名(参数类型 参数名,){ 方法体…}
构造方法 格式:public 类名(参数类型 参数名,){ 方法体…}
构造方法和普通方法的区别:1.构造方法没有返回值类型 2.构造方法名必须是类名
构造方法的作用:1.创建对象 2.同时给多个属性初始化
4.使用方法,根据保存的数据还原图形:
public void drawShape(Graphics g){}
(drawShape是方法名,(Graphics g)是传入的参数,用g调用drawline等绘图API)
5.粗细颜色重新获得:
g.setColor(color);
Graphics2D g2 = (Graphics2D)g;
BasicStroke stroke = new BasicStroke(lineWidth);
g2.setStroke(stroke);
6.使用switch(name){}实现对不同图形的精准重绘:
switch (name){
case "直线":
g.drawLine(x1,y1,x2,y2);
break;
case "矩形":
g.drawRect(x1,y1,x2,y2);
break;
case"任意三角形":
g.drawLine(x1,y1,x2,y2);
g.drawLine(x1,y1,x3,y3);
g.drawLine(x2,y2,x3,y3);
break;
case"多边形":
g.drawLine(x1,y1,x2,y2);
break;
case"曲线":
g.drawLine(x1,y1,x2,y2);
break;
case"橡皮擦":
g2.setStroke(new BasicStroke(5));
g.setColor(Color.WHITE);
g.drawLine(x1, y1, x2, y2);
break;
}
7.完整示例:
import java.awt.*;
/**
* @author xuqiang
* @date 2025/8/5 14:39
* @description
*/
public class Shapes {
public int x1,y1,x2,y2,x3,y3;
public String name="";
public Color color ;
public float lineWidth;
public Shapes(String name,Color color,float lineWidth,int x1,int y1,int x2,int y2,int x3,int y3){
this.name = name;
this.color = color;
this.lineWidth = lineWidth;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
}
public Shapes(String name,Color color,float lineWidth,int x1,int y1,int x2,int y2){
this.name = name;
this.color = color;
this.lineWidth = lineWidth;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public void drawShape(Graphics g){
g.setColor(color);
Graphics2D g2 = (Graphics2D)g;
BasicStroke stroke = new BasicStroke(lineWidth);
g2.setStroke(stroke);
switch (name){
case "直线":
g.drawLine(x1,y1,x2,y2);
break;
case "矩形":
g.drawRect(x1,y1,x2,y2);
break;
case"任意三角形":
g.drawLine(x1,y1,x2,y2);
g.drawLine(x1,y1,x3,y3);
g.drawLine(x2,y2,x3,y3);
break;
case"多边形":
g.drawLine(x1,y1,x2,y2);
break;
case"曲线":
g.drawLine(x1,y1,x2,y2);
break;
case"橡皮擦":
g2.setStroke(new BasicStroke(5));
g.setColor(Color.WHITE);
g.drawLine(x1, y1, x2, y2);
break;
}
}
}
在第四个Java class中------------------------------------------------------------
1.自定义MPanel继承JPanel:
public class MPanel extends JPanel {}
2.定义属性(数组):
public Shapes[] shapeArr;
3.在paint方法中实现自定义的功能:
public void paint(Graphics g) {
super.paint(g);
for (int i = 0; i < shapeArr.length; i++) {
Shapes shape = shapeArr[i];
if (shape != null) {
shape.drawShape(g);//防止空指针异常
}
}
}
4.完整示例:
import javax.swing.*;
import java.awt.*;
/**
* @author xuqiang
* @date 2025/8/5 14:38
* @description
*/
public class MPanel extends JPanel {
public Shapes[] shapeArr;
public void paint(Graphics g) {
super.paint(g);
for (int i = 0; i < shapeArr.length; i++) {
Shapes shape = shapeArr[i];
if (shape != null) {
shape.drawShape(g);
}
}
}
}
更多推荐

所有评论(0)