1、搭建基本窗口框架


此部分是关于和用户交互之间的窗口,及一些参数的配置


public class DrawTest02 extends JFrame{
    public void DrawTest02(){
        JFrame jframe = new JFrame("画板");//创建JFrame对象 并对画板窗口进行命名
        JFrame jFrame = this;
        jframe.setSize(1000,800);//设定窗口大小
        jframe.setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭窗口会结束当前运行状态
        jframe.setLocationRelativeTo(null);//设定画板页面中间
        jframe.setLayout(new FlowLayout());//创建流布局,自动根据窗口大小排列
        jframe.setVisible(true);//设定数据可视化开关
        jframe.addMouseListener(drawListenerA);//添加监听的对象
    }

创建工具类(颜色,坐标点等...)

class UtilityColor
{
    Color color;
    int x,x1,y,y1;
    String TypeName;

    public UtilityColor(Color color, int x, int x1, int y, int y1, String typeName) {
        this.color = color;
        this.x = x;
        this.x1 = x1;
        this.y = y;
        this.y1 = y1;
        TypeName = typeName;
    }
    public void drawShape(Graphics graphics)
    {
        graphics.setColor(color);
    }
}

2、封装图形实现过程

此处是对于图像绘制的过程进行封装,方便重复调用

class Line extends  UtilityColor{
    //继承UtilityColor中的属性,并重写其中的实例方法
    //这是因为子类之间的实现功能需求不同
    public Line(Color color, int x, int x1, int y, int y1, String typeName) {
        super(color, x, x1, y, y1, typeName);
    }
    public void drawShape(Graphics graphics){
        super.drawShape(graphics);
        graphics.drawLine(x,y,x1,y1);
    }
}

class  Rect extends UtilityColor{
    //继承UtilityColor中的属性,并重写其中的实例方法
    //这是因为子类之间的实现功能需求不同
    //由于此处我们有两个选项一个是实心矩形,一个不是
    //此处采用对于drawShpe方法重写中进行判断
    //注意:判断的内容要是什么,由于过程当中若是判断的是非实心矩形,
    //会造成实际画板上的内容,画一个非实心矩形,在使用实心矩形画不出来的情况
    //实心圆同理
    public Rect(Color color, int x, int x1, int y, int y1, String typeName) {
        super(color, x, x1, y, y1, typeName);
    }
    public void drawShape(Graphics graphics){
        super.drawShape(graphics);
        if(TypeName.equals("实心矩形")){
            graphics.fillRect(Math.min(x,y),Math.min(x1,y1),Math.abs(x - x1),Math.abs(y - y1));
        }else {

            graphics.drawRect(Math.min(x,y),Math.min(x1,y1),Math.abs(x - x1),Math.abs(y - y1));
        }
    }
}

class Oval extends  UtilityColor{
    //继承UtilityColor中的属性,并重写其中的实例方法
    //这是因为子类之间的实现功能需求不同

    public Oval(Color color, int x, int x1, int y, int y1, String typeName) {
        super(color, x, x1, y, y1, typeName);
    }

    @Override
    public void drawShape(Graphics graphics) {
        super.drawShape(graphics);
        if(TypeName.equals("实心圆")){
            graphics.fillOval(Math.min(x,y),Math.min(x1,y1),Math.abs(x - x1),Math.abs(y - y1));
        }else {
            graphics.drawOval(Math.min(x,y),Math.min(x1,y1),Math.abs(x - x1),Math.abs(y - y1));
        }
    }
}

class  ABC extends UtilityColor{//等腰三角
    
    //继承UtilityColor中的属性,并重写其中的实例方法
    //这是因为子类之间的实现功能需求不同
    public ABC(Color color, int x, int x1, int y, int y1, String typeName) {
        super(color, x, x1, y, y1, typeName);
    }

    @Override
    public void drawShape(Graphics graphics) {
        super.drawShape(graphics);
        int ix = (x + x1) /2;//顶点
        int ymin = Math.min(y,y1);
        int xmax = Math.max(x,x1);
        int xmin = Math.min(x,x1);
        int ymax = Math.max(y,y1);
        graphics.drawLine(ix,ymin,xmin,ymax);
        graphics.drawLine(xmin,ymax,xmax,ymax);
        graphics.drawLine(xmax,ymax,ix,ymin);

    }
}

3、窗口按键上色板块、图像名字,运用ArrayList数组进行存储,并由监听器进行监听

此处是关于鼠标、用户操作的监听器,和部分基本属性部分

class DrawListenerB implements MouseListener, ActionListener {
    /*
    ActionListener  接收操作事件的侦听器
    MouseListener   鼠标监听器
     */

    int x,x1,y,y1;//设定两个点  矩形 圆都是两点决定的
    int x2,y2,x3,y3,x4,y4;
    String Shape = "";
    Color color;
    Graphics graphics = null;//调入Graphics图形上下文的抽象基类 也可以叫做绘图的画笔
    ArrayList<UtilityColor> arrayList = new ArrayList<>();//存储数组
    
    public void setGraphics(Graphics graphics) {
        this.graphics = graphics;
    }
    
    int count = 0;//计数器
    @Override
    public void mouseClicked(MouseEvent e) {//鼠标点击时调用
        x = e.getX();  //返回事件相对于源组件的水平 x 坐标。
        y = e.getY();   //  返回事件相对于源组件的水平 y坐标。
        //尝试一下子点击的时候
        if(Shape.equals("三角形")){
            if(count == 0){
            x2 = x;
            y2 = y;
            count++;
            } else if(count == 1)
            {
                x3 = x;
                y3 = y;
                graphics.drawLine(x2,y2,x3,x3);
                count++;
            } else if(count == 2){
                x4 = x;
                y4 = y;
                graphics.drawLine(x3,y3,x4,y4);
                graphics.drawLine(x4,y4,x2,y2);
                count=0;
            }
        }
        int button = e.getButton (); //返回更改了状态的鼠标按键
    }

    @Override
    public void mousePressed(MouseEvent e) {//鼠标按下时调用
        x = e.getX();  //返回事件相对于源组件的水平 x 坐标。
        y = e.getY();   //  返回事件相对于源组件的水平 y坐标。
    }
    @Override
    public void mouseReleased(MouseEvent e) {//鼠标释放的时候调用
        x1 = e.getX();  //返回事件相对于源组件的水平 x 坐标。
        y1 = e.getY();   //  返回事件相对于源组件的水平 y坐标。
        switch (Shape){
            case "直线":
                Line line = new Line(color,x,y,x1,y1,Shape);
                line.drawShape(graphics);
                arrayList.add(line);//添加到数组当中
                break;
            case "矩形":
                Rect rect = new Rect(color,x,y,x1,y1,Shape);
                rect.drawShape(graphics);
                arrayList.add(rect);
                break;
            case "圆" :
                Oval oval = new Oval(color,x,y,x1,y1,Shape);
                oval.drawShape(graphics);
                arrayList.add(oval);
                break;
            case "实心矩形" :
                Rect fillRect = new Rect(color,x,y,x1,y1,Shape);
                fillRect.drawShape(graphics);
                arrayList.add(fillRect);
                break;
            case "实心圆":
                  Oval fillOvel = new Oval(color,x,y,x1,y1,Shape);
                  fillOvel.drawShape(graphics);
                  arrayList.add(fillOvel);
                  break;
            //上述四种情况都相同,两个点确定一个图像,所以可以使用过相同的参数
           
            case "等腰三角形" :
                ABC abc = new ABC(color,x,y,x1,y1,Shape);
                abc.drawShape(graphics);
                arrayList.add(abc);
                break;
            //思路:以矩形为参照物,矩形中点为顶点,之后两个点就是Math.min(x,x1) Math.max(y,y1)
            //另一个点 Math.max(x,x1),Math.max(y,y1)
            default:
                break;
        }


    }

    @Override
    public void mouseEntered(MouseEvent e) {
        
    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        MyButton myButton = (MyButton) e.getSource(); //get最初发生 Event 的对象
        int buttonId = myButton.getButtonId();//在接收事物监听器中判断接收的是颜色还是图像
        if(buttonId == MyButton.TYPE_SHAPE)
        {
            Shape  = myButton.getText();
            System.out.println(Shape);
        }
        else if(buttonId == MyButton.TYPE_COLOR) {
            System.out.println("颜色点击按钮");
            color = myButton.getBackground();
            graphics.setColor(color);
        }
    }
}
class MyButton extends JButton{
    //设定识别是否为颜色/图形设定相关变量
    private int ButtonId;

    public void setButtonId(int buttonId) {
        ButtonId = buttonId;
    }

    public  static final int TYPE_SHAPE=1;//若为1就是图像
    public  static final int TYPE_COLOR=0;//为0就是颜色

    public MyButton() {
        super("");
    }

    public MyButton(String text) {
        super(text);
    }

上面这个是关于上面代码块的判断图像和颜色的部分

 4、重写paint()方法

public void paint(Graphics graphics){
        super.paint(graphics);//重写paint方法重绘,这里会把画的图像地址保存到数组当中
        for (UtilityColor utilityColor : drawListenerA.arrayList) {
            utilityColor.drawShape(graphics);
        }
    }

5、把这写方法写到添加到主函数的无参方法中(方便调用)

public class DrawTest02 extends JFrame{
    DrawListenerB drawListenerA = new DrawListenerB();
    public void DrawTest02(){
        JFrame jframe = new JFrame("画板");
        JFrame jFrame = this;
        jframe.setSize(1000,800);
        jframe.setDefaultCloseOperation(EXIT_ON_CLOSE);
        jframe.setLocationRelativeTo(null);//设定画板页面中间

        jframe.setLayout(new FlowLayout());//创建流布局,自动根据窗口大小排列

        //设定按钮
        String  [] str = {"直线","矩形","圆","实心矩形","实心圆","等腰三角形","三角形","多边形"};
        for (int i = 0; i < str.length; i++) {
            MyButton myButton = new MyButton(str[i]);
            myButton.setButtonId(MyButton.TYPE_SHAPE);
            myButton.addActionListener(drawListenerA);//将监听器局部变量放到按钮中
            jframe.add(myButton);//把String数组中的东西呈现在窗口上
        }

        Color [] color = new Color[]{//添加颜色板块
          Color.BLACK,Color.BLUE,Color.GREEN,Color.LIGHT_GRAY,Color.ORANGE,Color.RED
          , Color.CYAN,Color.MAGENTA
        };

        //添加按钮功能
        for (int i = 0; i < color.length; i++) {
            MyButton myButton = new MyButton();
            myButton.setBackground(color[i]);
            myButton.setButtonId(MyButton.TYPE_COLOR);//此行由于没写其构造方法,所以运行前写不到面板上
            myButton.addActionListener(drawListenerA);
            myButton.setPreferredSize(new Dimension(50,50));//设定颜色板块大小
            jframe.add(myButton);
        }

        jframe.setVisible(true);//设定数据可视化开关
        jframe.addMouseListener(drawListenerA);//添加监听的对象
        drawListenerA.setGraphics(jframe.getGraphics());
//         为组件创建一个图形上下文。

    }

6、最后调用主函数

public static void main(String[] args) {
        new DrawTest02().DrawTest02();
    }

图像展示

javafx画板 java创建画板应用程序_数组

 


结语:当前写出来的画板和大家电脑上的画板还有很大的差距.....

之后慢慢完善吧ahhh,欢迎各位大佬指点(抱拳)!!!!