Java小项目——画板

一、项目设计

1、界面设计JFrame

上面为控制栏JPanel

下面为绘制面板JPanel

2、基本思路

鼠标事件监听器:展示一个JPanel界面,添加鼠标事件监听器,记录鼠标点击事件的坐标;

getGraphics()方法:可以得到java.awt.Graphics对象gr,gr作为“画笔”,调用draw方法并传入坐标,可以绘制相应图像。

3、具体功能

3.1、绘制方式:

画直线:

g.drawLine(x1,y1,x2,y2);

画矩形:

g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));

画多边形:

若为第一次单击,保存该坐标;非第一次单击,绘制两个单击之间的直线;双击后,绘制第一次单击和本次双击坐标之间的直线,再清空所有坐标。

拖动绘制:

拖动鼠标中,不断绘制两个时间段之间两点之间的直线。

3.2、颜色选取

可以选取对应颜色进行绘制

3.3、重绘

改变窗体大小时,会调用paint()函数,重绘。

需要在这个函数中,写重绘已经绘制的图形的代码,用于保存代码。

二、初步实现:界面实现+绘制直线

1、主函数部分:SampleDraw类

package Draw;

import javax.swing.*;
import java.awt.*;

public class SampleDraw {
    public static void main(String args[]){
        SampleDraw draw = new SampleDraw();
        draw.showUI();
    }

    public void showUI(){
//主界面JFrame jf
        JFrame jf = new JFrame();
        jf.setTitle("画图1.0");
        jf.setSize(800,800);
        jf.setLocationRelativeTo(null);
        jf.setDefaultCloseOperation(3);
        
        //控制台JPanel jp1+绘制界面JPanel jp2
        JPanel jp1 = new JPanel();
        JPanel jp2 = new JPanel();
        jp1.setBackground(java.awt.Color.white);
        jf.add(jp1,BorderLayout.NORTH);
        jf.add(jp2,BorderLayout.CENTER);
        
        //按钮:前四个为绘制功能;后两个为颜色选择
        JButton jb1 = new JButton("线条");
        JButton jb2 = new JButton("矩形");
        JButton jb3 = new JButton("多边形");
        JButton jb4 = new JButton("绘制");
        JButton jbc1 = new JButton("蓝色");
        JButton jbc2 = new JButton("绿色");
        jbc1.setForeground(Color.blue);
        jbc2.setForeground(Color.green);
        //jbc2.setBackground(Color.BLACK);
        jp1.add(jb1);
        jp1.add(jb2);
        jp1.add(jb3);
        jp1.add(jb4);
        jp1.add(jbc1);
        jp1.add(jbc2);

        //可见放在add之后,获取之前
        jf.setVisible(true);

        //创建画笔对象gr,添加至jpanel2
        Graphics gr = jp2.getGraphics();
        
        //鼠标监听器对象mouse
        //构造函数初始化:使得鼠标中的位置,获取画布类:鼠标在画布上画线、多边形
        addMouseListener mouse = new addMouseListener(gr);
        
        //在各个事件源(组件)上添加鼠标监听器
        jp2.addMouseListener(mouse);
        jp2.addMouseMotionListener(mouse);
        jb1.addActionListener(mouse);
        jb2.addActionListener(mouse);
        jb3.addActionListener(mouse);
        jb4.addActionListener(mouse);
        jbc1.addActionListener(mouse);
        jbc2.addActionListener(mouse);
    }
}

2、事件监听器部分:addMouseListener类,继承了多个动作监听器接口

2.1 首先在actionPerformed获取目前状态:画什么,用什么颜色

2.2 在按下去 mousePressed 、释放 mouseReleased 中分别获取当时坐标,用绘制函数绘制直线和矩形

if(name.equals("线条")||name.equals("")){
    g.drawLine(x1,y1,x2,y2);
}

if(name.equals("矩形")){
    g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
}

2.3 在点击mouseClicked中,用函数绘制多边形

第一次按压记录x0;第二次之后,绘制上一次点击位置和本次点击位置的直线;双击之后,绘制上一次点击位置和本次点击位置+x0与本次双击点的两条直线

g.drawLine(x01,y01,x02,y02); //第二次以后
g.drawLine(x0,y0,x01,y01);   //双击后

2.4 在拖拽mouseDragged中,绘制两次时间段之间的直线,时间段片小,则显示出来像曲线

g.drawLine(x,y,xt,yt);
package Draw;

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;
import java.awt.event.MouseMotionListener;

//MouseListener:绘制直线、矩形、多边形
//ActionListener:动作监听,获取button的text,来判断目前处于何种工作状态
//MouseMotionListener:拖动画线
public class addMouseListener implements MouseListener ,ActionListener , MouseMotionListener{
    //变量如下,分别对应直线、矩形x1,x2;多边形x01,x02,x0;
    private int x1=0,y1=0,x2=0,y2=0;
    private int x=0,y=0,xt=0,yt=0;
    private int x01,y01,x02,y02,x0,y0;
    private Graphics g ;
    private String name = "线条";
    private Color jbcolor = Color.BLACK;

    //构造方法,将画笔传入监听器,在监听器中动作执行时,绘制相应图形
    public addMouseListener(Graphics gr){
        this.g = gr;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        //3-多边形绘制,最后双击,在第一个点和最后一个点的位置之间画线
        if(e.getClickCount()==2){
            System.out.println("双击!!");
            g.drawLine(x0,y0,x01,y01);
            x0=0;y0=0;x01=0;y01=0;x02=0;y02=0;
        }
        System.out.println("点击");

        if(name.equals("多边形")) {
            //当第一次按压,x01=0时候,则将第一次按压坐标存入x0,y0
            if(x01==0){
                x0 = e.getX();
                y0 = e.getY();
            }
            x01 = e.getX();
            y01 = e.getY();
            //第二次按压以后画线
            if (x02!=0){
                g.drawLine(x01,y01,x02,y02);

            }
            //将本次x01按压存入x02,用于下一次绘制直线
            x02 = x01;
            y02 = y01;
        }

    }

    @Override
    public void mousePressed(MouseEvent e) {
        //1线条-2矩形-按压时为绘制起点x1,y1
        System.out.println("按压");
        x1 = e.getX();
        y1 = e.getY();

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        //1线条-2矩形-释放时为绘制终点x2,y2
        System.out.println("释放");
        x=0;y=0;xt=0;yt=0;
        x2 = e.getX();
        y2 = e.getY();
        //
        if(name.equals("线条")||name.equals("")){
            g.drawLine(x1,y1,x2,y2);
        }

        if(name.equals("矩形")){
            g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        System.out.println("进入");
    }

    @Override
    public void mouseExited(MouseEvent e) {
        System.out.println("离开");
    }


    @Override
    public void mouseDragged(MouseEvent e) {
        //拖动绘制
        if(name.equals("绘制")){
            x = e.getX();
            y = e.getY();
            if(xt!=0){
                g.drawLine(x,y,xt,yt);
            }
            xt = x;
            yt = y;
        }

    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }

    @Override
    public void actionPerformed(ActionEvent e) {

        if(e.getActionCommand().equals("蓝色")){
            //定义新的jb按钮对象,来接受e.getSource()的object对象,强制转型为JButton
            JButton jb = (JButton)e.getSource();
            jbcolor = jb.getForeground();
            g.setColor(jbcolor);
        }else if(e.getActionCommand().equals("绿色")){
            JButton jb = (JButton)e.getSource();
            jbcolor = jb.getForeground();
            g.setColor(jbcolor);
        }else{
            name = e.getActionCommand();
        }

        System.out.println("button:"+name);

    }
}

   结果:如下   

三、重绘    ❤️【本章节三个类组成最终代码】❤️

1、需要重绘,则需要数组存储下绘制过的线条

定义Shape类

属性:包括初始坐标、终止坐标、绘制形状、颜色

方法:重新画方法,调用该方法,将shape中的对象重新绘制出来

package com.java7.DrawRedraw0710;

import java.awt.*;

public class Shape {
    private int x1,y1,x2,y2;
    private String name;
    private Color color;

    public Shape(int x1,int y1,int x2,int y2,String name,Color color){
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        this.name = name;
        this.color = color;
    }
    //重绘中,调用Redraw,则绘制shape对象
    public void Redraw(Graphics g){
        System.out.println("Graphics name = "+name);
        g.setColor(color);
        switch (name){
            case "线条":
                g.drawLine(x1,y1,x2,y2);
                break;
            case "矩形":
                g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
                break;
        }
    }
}

2、定义好shape类后,我们需要在在监听器类,绘制的时候,将坐标、颜色、绘制种类存入Shape,再将Shape存入ShapeArray[]数组。

//1.把线条坐标、名称存入Shape
Shape shape = new Shape(x1,y1,x2,y2,name,jbcolor);
shapeArray[index++] = shape;
//3.1.单击后,把多边形的初始坐标、名称存入Shape
Shape shape = new Shape(x01,y01,x02,y02,"线条",jbcolor);
shapeArray[index++] = shape;
//3.2.双击后,把多边形的初次按下坐标+最后按压的坐标、名称存入Shape;清空所有坐标,用于下一次判断是否为第一次按压
Shape shape = new Shape(x0,y0,x01,y01,"线条",jbcolor);
shapeArray[index++] = shape;
x0=0;y0=0;x01=0;y01=0;x02=0;y02=0;

源码:addMouseListener类

package com.java7.DrawRedraw0710;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class addMouseListener implements MouseListener ,ActionListener , MouseMotionListener{

    private int x1=0,y1=0,x2=0,y2=0;
    private int x=0,y=0,xt=0,yt=0;
    private int x01,y01,x02,y02,x0,y0;
    private Graphics g ;
    private String name = "线条";
    private Color jbcolor=Color.BLACK;

    //重绘:
    private Shape shapeArray[];
    private int index = 0;
    //set函数,使用后,初始化画笔gr,shapeArray[]数组,用于将其传入addMouseListener
    public void setGr(Graphics gr){
        this.g = gr;
    }
    public void setSa(Shape shapeArray[]){
        this.shapeArray = shapeArray;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if(e.getClickCount()==2){
            g.drawLine(x0,y0,x01,y01);
            //3.2.双击后,把多边形的初次按下坐标+最后按压的坐标、名称存入Shape
            Shape shape = new Shape(x0,y0,x01,y01,"线条",jbcolor);
            shapeArray[index++] = shape;
            x0=0;y0=0;x01=0;y01=0;x02=0;y02=0;
        }
    }

    public void mousePressed(MouseEvent e) {
        //System.out.println("按压");
        x1 = e.getX();
        y1 = e.getY();

    }

    public void mouseReleased(MouseEvent e) {
        x=0;y=0;xt=0;yt=0;
        x2 = e.getX();
        y2 = e.getY();
        System.out.println("name="+name);
        if(name.equals("线条")||name.equals("")){
            g.drawLine(x1,y1,x2,y2);
            //1.把线条坐标、名称存入Shape
            Shape shape = new Shape(x1,y1,x2,y2,name,jbcolor);
            shapeArray[index++] = shape;
        }

        if(name.equals("矩形")){
            g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
            //2.把矩形坐标、名称存入Shape
            Shape shape = new Shape(x1,y1,x2,y2,name,jbcolor);
            shapeArray[index++] = shape;
        }

        if(name.equals("多边形")) {
            System.out.println("多边形");
            if(x01==0){//第一次按下,记录地刺次按下的位置,用于双击后,多边形闭合
                x0 = e.getX();
                y0 = e.getY();
            }
            x01 = e.getX();
            y01 = e.getY();

            if (x02!=0){//第二次按压
                g.drawLine(x01,y01,x02,y02);
                //3.1.单击后,把多边形的初始坐标、名称存入Shape
                Shape shape = new Shape(x01,y01,x02,y02,"线条",jbcolor);
                shapeArray[index++] = shape;
            }
            x02 = x01;
            y02 = y01;
        }
    }

    public void mouseEntered(MouseEvent e) {
        ///System.out.println("进入");
    }

    public void mouseExited(MouseEvent e) {
        //System.out.println("离开");
    }


    public void mouseDragged(MouseEvent e) {
        if(name.equals("绘制")){
            System.out.println("DRAGE —— 拖动绘制曲线:");
            x = e.getX();
            y = e.getY();
            if(xt!=0){
                g.drawLine(x,y,xt,yt);
                //把坐标、名称存入Shape
                Shape shape = new Shape(x,y,xt,yt,"线条",jbcolor);
                shapeArray[index++] = shape;
            }
            xt = x;
            yt = y;
        }
    }

    public void mouseMoved(MouseEvent e) {
    }

    public void actionPerformed(ActionEvent e) {
        //首先获取jb对象(JButton)e.getSource();再对象的颜色jb.getBackground()
        if("".equals(e.getActionCommand())){
            JButton jb = (JButton)e.getSource();
            jbcolor = jb.getBackground();
            g.setColor(jbcolor);
        }
        //获取动作:直线、矩形、多边形、拖动绘制线条
        else{
            name = e.getActionCommand();
            System.out.println("button:"+name);
        }
    }
}

3、 主函数,继承JPanel,在重写panit()函数时,写入:绘制shapeArray[]数组中所有的Shape对象。

@Override
public void paint(Graphics g) {
    //调用重绘
    super.paint(g);
    for(int i=0;i<shapeArray.length;i++){
        if(shapeArray[i]!=null){
            shapeArray[i].Redraw(g);
        }
        else
            break;
    }
    System.out.println("重绘");
}

源码:SampleDraw

package com.java7.DrawRedraw0710;

import javax.swing.*;
import java.awt.*;

public class SampleDraw extends JPanel{
    public static void main(String args[]){
        SampleDraw draw = new SampleDraw();
        draw.showUI();
    }
    private Shape shapeArray[]=new Shape[1000];

    @Override
    public void paint(Graphics g) {
        //调用重绘
        super.paint(g);
        for(int i=0;i<shapeArray.length;i++){
            if(shapeArray[i]!=null){
                shapeArray[i].Redraw(g);
            }
            else
                break;
        }
        System.out.println("重绘");
    }

    public void showUI(){
        //界面
        JFrame jf = new JFrame();
        jf.setTitle("画图1.0");
        jf.setSize(800,800);
        jf.setLocationRelativeTo(null);
        jf.setDefaultCloseOperation(3);

        //JPanel
        JPanel jp1 = new JPanel();
        jp1.setBackground(Color.white);
        jf.add(jp1,BorderLayout.NORTH);
        jf.add(this,BorderLayout.CENTER);

        //按钮
        JButton jb1 = new JButton("线条");
        JButton jb2 = new JButton("矩形");
        JButton jb3 = new JButton("多边形");
        JButton jb4 = new JButton("绘制");

        jp1.add(jb1);
        jp1.add(jb2);
        jp1.add(jb3);
        jp1.add(jb4);

        //鼠标监听器,初始化设置shapeArray
        addMouseListener mouse = new addMouseListener();

        //颜色数组,循环添加颜色按钮
        Color colorArray[] = {Color.GREEN,Color.BLUE,Color.CYAN};
        for(int i=0;i<colorArray.length;i++){
            JButton jb = new JButton();
            jb.setBackground(colorArray[i]);
            jb.setForeground(colorArray[i]);
            jp1.add(jb);
            jb.addActionListener(mouse);
        }

        //可见放在add之后,获取之前
        jf.setVisible(true);

        //画布,添加至jpanel2
        Graphics gr = this.getGraphics();
        System.out.println("graphics = " + gr);

        //添加鼠标监听器
        this.addMouseListener(mouse);
        this.addMouseMotionListener(mouse);

        jb1.addActionListener(mouse);
        jb2.addActionListener(mouse);
        jb3.addActionListener(mouse);
        jb4.addActionListener(mouse);

        mouse.setGr(gr);//使得鼠标中的位置,获取画布类:鼠标在画布上画线、多边形
        mouse.setSa(shapeArray);//获得shapeArray,用于paint中重绘

    }

}

结果:

原文地址:https://www.cnblogs.com/iriswang/p/11084649.html