重绘: 鼠标在窗体或者面板中绘制图形时,当窗体的尺寸被改变时,窗体中的直线会消失,原因是当窗体改变时尺寸时会刷新,重新绘制一遍窗体,由于绘制的直线不包括在窗体源码中,所以直线会消失
解决办法:
1: 继承JFrame 、重写窗体的paint方法,将直线绘制在窗体上 (paint方法: 窗体被改变时调用的方法)
2: 将绘制的图形保存起来
①: 创建一个图形类(属性就是图形的各种数据)
属性: 坐标 图形名 颜色 线条粗细.....
方法: 根据数据来绘制图形
②: 在绘制图形时,创建图形对象,将数据存入对象中、同时还要调用图形的绘制方法 进行绘制
③: 将创建好的图形对象存储在一个图形数组中
下面就利用代码具体实现一下:
先创建一个DrawPad类,创建一个窗体画板,添加一些按钮、颜色、滑杆组件。按钮设置为绘制图形选项,可以绘制直线、矩形、圆形、三角形的图形选项;颜色按钮来改变画笔颜色;滑杆可以控制线条的粗细。
package ChongHui;
import javax.swing.*;
import java.awt.*;
public class DrawPad {
public static void main(String[] args){
DrawPad dp = new DrawPad ();
dp.initUI ();
}
// 创建监听器对象
DrawListener dl = new DrawListener ();
//创建画板
public void initUI(){
JFrame jf = new JFrame ();
jf.setTitle ("画图板");
jf.setSize (900, 750);
jf.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
jf.setLocationRelativeTo (null);
jf.setLayout (new FlowLayout ());
String[] strs = {"直线", "矩形", "圆形", "三角形"};
for(int i = 0; i < strs.length; i++){
JButton btn1 = new JButton (strs[i]);
jf.add (btn1);
btn1.addActionListener (dl);
}
Color[] colors = {Color.BLACK, Color.WHITE, Color.GRAY,
Color.LIGHT_GRAY, Color.DARK_GRAY, Color.RED,
Color.PINK, Color.ORANGE, Color.YELLOW, Color.GREEN,
Color.MAGENTA, Color.CYAN, Color.BLUE};
for(int i = 0; i < colors.length; i++){
JButton btn2 = new JButton ();
btn2.setBackground (colors[i]);
btn2.setPreferredSize (new Dimension (30, 30));
jf.add (btn2);
btn2.addActionListener (dl);
}
// 滑杆
JLabel jslLabel = new JLabel ("画笔粗细: ");
jf.add (jslLabel);
JSlider jsl =new JSlider (0,50,2);
jf.add (jsl);
jsl.addChangeListener (dl);
jf.setVisible (true);
// 添加监听
jf.addMouseListener (dl);
// 获取画笔
Graphics g = jf.getGraphics ();
// 初始化监听器中的画笔
dl.g = g;
// 初始化jf中dl
// jf.dl = dl;
}
}
窗体中所需要的添加完成后,此时的按钮和画笔以及滑杆是没有灵魂的,我们就需要为按钮添加监听功能。需要创建一个DrawListener的监听器类,利用接口继承动作、鼠标、更改的属性和方法。在监听器类中设置初始颜色为黑色,如果不设置的话,此时我们并没有选择画笔的颜色,导致图形在画板中无法显示。在监听器中,我们获取按钮对象、滑杆对象、颜色对象所对应的值,来改变线条的粗细、画笔的颜色、形状的选择。
package ChongHui;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
public class DrawListener implements ActionListener, MouseListener,ChangeListener{
Graphics g;
int x1, y1, x2, y2;
String type = "直线";
Color color = Color.black;
int strokeValue= 1;
ArrayList<Shape> shapeList = new ArrayList<> ();
@Override
public void stateChanged(ChangeEvent e){
// 获取滑杆对象
JSlider slider = (JSlider) e.getSource ();
// 获取滑杆的值
strokeValue = slider.getValue ();
// 将值设置为画笔的粗细
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke (new BasicStroke (strokeValue));
}
@Override
public void actionPerformed(ActionEvent e){
String ac = e.getActionCommand ();
System.out.println ("ac:" + ac);
if(ac.equals ("")){// 点击的是颜色按钮
// 获取按钮对象
JButton btn = (JButton) e.getSource ();
// 获取按钮对象的背景色
color = btn.getBackground ();
// 设置画笔颜色
g.setColor (color);
} else{
type = ac;
}
}
@Override
public void mouseClicked(MouseEvent e){
}
@Override
public void mousePressed(MouseEvent e){
x1 = e.getX ();
y1 = e.getY ();
}
@Override
public void mouseReleased(MouseEvent e){
x2 = e.getX ();
y2 = e.getY ();
if(type.equals ("直线") || type.equals ("矩形") || type.equals("圆形") || type.equals("三角形")){
// 创建图形对象
Shape shape = new Shape (type, x1, y1, x2, y2,color,strokeValue);
// 绘制图形
shape.drawShape (g);
// 存储图形对象到数组中
shapeList.add (shape);
}
}
@Override
public void mouseEntered(MouseEvent e){
}
@Override
public void mouseExited(MouseEvent e){
}
}
为了解决改变窗体尺寸时,窗体刷新内容消失的问题。我们需要创建一个数组存储图形对象,因此创建一个Shape类,用来存储在窗体中绘制的图形,保存各形状的顶点参数。
package ChongHui;
import java.awt.*;
public class Shape {
String typeName;
int x1, y1, x2, y2;
Color color;
int strokeValue;// 画笔粗细
public Shape(String typeName,int x1,int y1,int x2,int y2,Color color,int strokeValue){
this.typeName = typeName;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2= y2;
this.color = color;
this.strokeValue = strokeValue;
}
public void drawShape(Graphics g){
g.setColor (color);
Graphics2D g2d= (Graphics2D) g;
g2d.setStroke (new BasicStroke (strokeValue));
if(typeName.equals ("直线")){
g.drawLine (x1, y1, x2, y2);
} else if(typeName.equals ("矩形")){
g.drawRect (x1, y1, x2 - x1, y2 - y1);
} else if(typeName.equals ("圆形")){
g.drawOval (x1, y1, x2 - x1, y2 - y1);
}
// else if(typeName.equals ("三角形")){
// g.drawPolygon(new int[] {10, 20, 30}, new int[] {100, 20, 100}, 3);
// }
}
}