为什么需要方法重绘?因为窗体改变的时候会刷新,会把所有的绘制图形给覆盖了,图形重绘可以保存图形,并且把图形在刷新的时候再绘制出来。
直线 以及各种图形如何保存 ?
以面向对象的思维看待图形
图形:直线 矩形 圆 :
属性:图形名 坐标 颜色 ...
方法:绘制方法
在什么时候绘制出来 ?
窗体刷新的时候绘制
继承Jframe 重写paint方法
在paint方法中将监听器图形数组中保存好的图形对象遍历取出 调用绘制方法
接下来我们讲具体实现方法:
1像之前学的一样创建一个类
public class DrawUI extends Jframe { public void showDrawUI(){ Jframe jf = new Jframe ; jf.setTitle("图形重绘"); jf.setSize(800,800); jf.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { DrawUI drawui = new DrawUI(); drawui.showDrawUI(); } }2.创建鼠标监听器,传入画笔,这样方便之后绘制
public class DrawListener implements MouseListener{ int x1, y1, x2, y2; Graphics g;// 需要给Graphics 传递一个画笔对象 @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 (); g.drawLine (x1,y1,x2,y2); //绘制一条直线 } @Override public void mouseEntered(MouseEvent e){ } @Override public void mouseExited(MouseEvent e){ } }3.给窗体添加鼠标监听器
public class DrawUI extends Jframe { public void showDrawUI(){ Jframe jf = new Jframe ; jf.setTitle("图形重绘"); jf.setSize(800,800); jf.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); jf.setVisible(true); DrawListener dr = new DrawListener();// 给窗体添加鼠标监听器 jf.addMouseListener(dr); //传入画笔 Graphics g = jf.getGraphics; dr.g = g;// 传给监听器对象中的画笔 g } public static void main(String[] args) { DrawUI drawui = new DrawUI(); drawui.showDrawUI(); } }4.前面讲到 直线以及各种图形如何保存 ?:以面向对象的思维看待图形
所以我们要单独建立一个Shape类来让图形绘画出来,类中一定有方法和属性。
public class Shape{ String typename;//属性 int x1,y1,x2,y2; Color color; public void drawShape(Graphics g){//方法 g.setColor (color); if(typename.equals ("直线")){ g.drawLine (x1,y1,x2,y2); }else if(typename.equals ("矩形")){ g.drawRect (Math.min (x1,x2),Math.min (y1,y2),Math.abs (x2-x1),Math.abs (y2-y1)); }else if(typename.equals ("圆")){ g.drawOval (Math.min (x1,x2),Math.min (y1,y2),Math.abs (x2-x1),Math.abs (y2-y1)); }else if(typename.equals("实心圆")){ g.fillOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2)); }else if(typename.equals("实心矩形")){ g.fillRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2)); } } public static void main(String[] args) { } }5.如何将Shape和前面连接起来呢?、
要在监听器中创建Shape对象:
// Shape 对象创建
Shape shape = new Shape ();
shape.typename="矩形";
shape.color=Color.RED;
shape.x1=x1;
shape.y1=y1;
shape.x2=x2;
shape.y2=y2;// 绘制图形 调用的是图形的绘制方法
shape.drawShape (g);因为要画很多次图形,所以应该用数组把他们保存起来:
Shape[] shapeList = new Shape[100];
int shapeindex=0;// 将每次绘制的图形对象保存至数组中
shapeList[shapeindex++]=shape;
System.out.println ("已经保存了"+shapeindex+"个图形!!");import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; public class DrawListener implements MouseListener{ int x1, y1, x2, y2; Graphics g;// 需要给Graphics 传递一个画笔对象 @Override public void mouseClicked(MouseEvent e){ } @Override public void mousePressed(MouseEvent e){ x1 = e.getX (); y1 = e.getY (); } Shape[] shapeList = new Shape[100]; int shapeindex=0;//记录链表下标 @Override public void mouseReleased(MouseEvent e){ x2 = e.getX (); y2 = e.getY (); // g.drawLine (x1,y1,x2,y2); // Shape 对象创建 Shape shape = new Shape (); shape.typename="矩形"; shape.color=Color.RED; shape.x1=x1; shape.y1=y1; shape.x2=x2; shape.y2=y2; // 绘制图形 调用的是图形的绘制方法 shape.drawShape (g); // 将每次绘制的图形对象保存至数组中 shapeList[shapeindex++]=shape; System.out.println ("已经保存了"+shapeindex+"个图形!!"); } @Override public void mouseEntered(MouseEvent e){ } @Override public void mouseExited(MouseEvent e){ } }6. 重写界面的刷新方法,重写的方法会被子类以及子类对象优先调用
前面有讲到:窗体刷新的时候绘制,继承Jframe 重写paint方法, 在paint方法中将监听器图形数组中保存好的图形对象遍历取出,调用绘制方法。
具体操作如下:
public void paint(Graphics g){
super.paint (g);
// 从监听器中拿到存储图形的数组
// dl.shapeList;
for(int i = 0; i < dl.shapeIndex; i++){
Shape shape = dl.shapeList[i];
shape.drawShape (g);
}}
public class DrawUI extends Jframe{ //extends:用于DrawUI继承Jframe的关键字 DrawListener dr = new DrawListener (); //将创建的监听器放到最外面是为了方便下面的所以类都可以调用它 public void showUI(){ // Jframe jf = new Jframe; //因为继承了Jframe所以只用写this就行,下面的jf也可以用this来代替 Jframe jf = this; jf.setTitle ("图形图像绘制"); jf.setSize (800,800); jf.setDefaultCloseOperation (Jframe.EXIT_ON_CLOSE); jf.setVisible (true); jf.addMouseListener (dr);// 给窗体添加鼠标监听器 Graphics g = jf.getGraphics (); dr.g=g;// 传给监听器对象中的画笔 g } // 重写界面的刷新方法 @Override public void paint(Graphics g){ super.paint (g); // 从监听器中拿到存储图形的数组 // dr.shapeList; for(int i = 0; i < dr.shapeindex; i++){ Shape shape = dr.shapeList[i]; shape.drawShape (g); } } public static void main(String[] args){ DrawUI drawui = new DrawUI (); drawui.showUI (); } }
已经了解了最基本的方法那么接下来我们完成如何添加按钮,进行颜色选择,并且绘制出想要的图案
1.首先,要加入在窗体中加入按钮监听器和鼠标监听器,这样才能实现功能:
FlowLayout fl = new FlowLayout(); jf.setLayout(fl);
JButton btn = new JButton(); jf.add(btn); btn.addActionListener(null);
DrawListener dr = new DrawListener();
jf.addMouseListener(dr); Graphics g = jf.getGraphics(); dr.g = g;
但由于我们有许多的按钮,所以可以考虑用数组的方法来存储建立,并且用封装的思想来依次建立监听器,使代码更加简洁,方法如下:
//建立按钮所需的数组
String[] strs = {"直线", "圆", "矩形", "实心圆", "实心矩形"};
Color[] color ={Color.WHITE,Color.BLACK,Color.yellow,Color.magenta,Color.DARK_GRAY};
//封装好可重复调用的直线FlowLayout fl = new FlowLayout(); jf.setLayout(fl); for(int i=0;i
完整代码如下:
package lyq220104图形重绘;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class DrawUI extends Jframe {
String[] strs = {"直线", "圆", "矩形", "实心圆", "实心矩形"};
Color[] color = {Color.WHITE,Color.BLACK,Color.yellow,Color.magenta,Color.DARK_GRAY};
DrawListener dr = new DrawListener();//放到最前面,这样就可以让showDrawUI和Paint函数都能用到他们
public void showDrawUI(){
Jframe jf = this ;
this.setTitle("图形重绘");
this.setSize(800,800);
jf.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);
jf.setVisible(true);
FlowLayout fl = new FlowLayout();
jf.setLayout(fl);
for(int i=0;i
2.既然窗体已经建立好,那么监听器部分的代码我们也要进行修改
//implements作为接口连接鼠标监听器和按钮监听器
public class DrawListener implements MouseListener, ActionListener
public void actionPerformed(ActionEvent e) {
System.out.println("按钮被点击");
String str = e.getActionCommand();
//例如 JButton aButton = new JButton("Today");
// getActionCommand()可以获取到Today
// getSource()获取到的是aButton
if (str.equals("")){
System.out.println("这是一个颜色按钮");
//获取点击的对象 按钮
JButton jb = (JButton) e.getSource();
//获取按钮背景颜色
color = jb.getBackground();
//设置给画笔对象
g.setColor(color);
}else{
//如果不是空格 那就把字符存入typeStr
typeStr = str;
}
}
//初始化
int x1,x2,y1,y2;
Graphics g;
Color color = Color.black;
String typeStr ="直线";
Shape[] shapeList = new Shape[100];
int shapeindex = 0;
@Override
public void mouseReleased(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
Shape shape = new Shape ();
shape.setshapeData(typeStr,x1,x2,y1,y2,color);
// 绘制图形 调用的是图形的绘制方法
shape.drawshape(g);
// 将每次绘制的图形对象保存至数组中
shapeList[shapeindex++] = shape;
System.out.println("已经保存了"+shapeindex+"个图形");
}
完整代码如下:
package lyq220104图形重绘;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class DrawListener implements MouseListener, ActionListener {
int x1,x2,y1,y2;
Graphics g;
Color color = Color.black;
String typeStr ="直线";
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按钮被点击");
String str = e.getActionCommand(); //例如 JButton aButton = new JButton("Today");
// getActionCommand()可以获取到Today
// getSource()获取到的是aButton
if (str.equals("")){
System.out.println("这是一个颜色按钮");
//获取点击的对象 按钮
JButton jb = (JButton) e.getSource();
//获取按钮背景颜色
color = jb.getBackground();
//设置给画笔对象
g.setColor(color);
}else{
//如果不是空格 那就把字符存入typeStr
typeStr = str;
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
Shape[] shapeList = new Shape[100];
int shapeindex = 0;
@Override
public void mouseReleased(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
Shape shape = new Shape ();
shape.setshapeData(typeStr,x1,x2,y1,y2,color);
// 绘制图形 调用的是图形的绘制方法
shape.drawshape(g);
// 将每次绘制的图形对象保存至数组中
shapeList[shapeindex++] = shape;
System.out.println("已经保存了"+shapeindex+"个图形");
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
3.那么Shape中也需要设置图形数据,才能连接成功,完整代码如下:
package lyq220104图形重绘;
import java.awt.*;
public class Shape {
String typename;
int x1,x2,y1,y2;
Color color;
//设置图形数据
public void setshapeData(String typename, int x1, int x2, int y1, int y2, Color color) {
this.typename = typename;
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.color = color;
}
public void drawshape(Graphics g){
if(typename.equals("直线")){
g.drawLine(x1,y1,x2,y2);
}else if(typename.equals("矩形")){
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}else if(typename.equals("圆")){
g.drawOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}else if(typename.equals("实心圆")){
g.fillOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}else if(typename.equals("实心矩形")){
g.fillRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
}
public static void main(String[] args) {
}
}
内容已经全部讲完,接下来请看全部完整代码:
package lyq220104图形重绘;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class DrawUI extends Jframe {
String[] strs = {"直线", "圆", "矩形", "实心圆", "实心矩形"};
Color[] color = {Color.WHITE,Color.BLACK,Color.yellow,Color.magenta,Color.DARK_GRAY};
DrawListener dr = new DrawListener();//放到最前面,这样就可以让showDrawUI和Paint函数都能用到他们
public void showDrawUI(){
Jframe jf = this ;
this.setTitle("图形重绘");
this.setSize(800,800);
jf.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);
jf.setVisible(true);
FlowLayout fl = new FlowLayout();
jf.setLayout(fl);
for(int i=0;i
package lyq220104图形重绘;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class DrawListener implements MouseListener, ActionListener {
int x1,x2,y1,y2;
Graphics g;
Color color = Color.black;
String typeStr ="直线";
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按钮被点击");
String str = e.getActionCommand(); //例如 JButton aButton = new JButton("Today");
// getActionCommand()可以获取到Today
// getSource()获取到的是aButton
if (str.equals("")){
System.out.println("这是一个颜色按钮");
//获取点击的对象 按钮
JButton jb = (JButton) e.getSource();
//获取按钮背景颜色
color = jb.getBackground();
//设置给画笔对象
g.setColor(color);
}else{
//如果不是空格 那就把字符存入typeStr
typeStr = str;
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
Shape[] shapeList = new Shape[100];
int shapeindex = 0;
@Override
public void mouseReleased(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
Shape shape = new Shape ();
shape.setshapeData(typeStr,x1,x2,y1,y2,color);
// 绘制图形 调用的是图形的绘制方法
shape.drawshape(g);
// 将每次绘制的图形对象保存至数组中
shapeList[shapeindex++] = shape;
System.out.println("已经保存了"+shapeindex+"个图形");
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
package lyq220104图形重绘;
import java.awt.*;
public class Shape {
String typename;
int x1,x2,y1,y2;
Color color;
//设置图形数据
public void setshapeData(String typename, int x1, int x2, int y1, int y2, Color color) {
this.typename = typename;
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.color = color;
}
public void drawshape(Graphics g){
if(typename.equals("直线")){
g.drawLine(x1,y1,x2,y2);
}else if(typename.equals("矩形")){
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}else if(typename.equals("圆")){
g.drawOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}else if(typename.equals("实心圆")){
g.fillOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}else if(typename.equals("实心矩形")){
g.fillRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
}
public static void main(String[] args) {
}
}



