Java学习记录 : 画板的实现

本文是作者学习Java的一个实践项目,通过实现一个简单的画板应用,介绍了如何使用Graphics类进行图形绘制,包括画直线、多边形等。作者在实现过程中遇到了线条拖拽时的显示问题,探讨了多种解决方案,并最终采用链表来存储和重新绘制所有线条,以实现平滑的拖拽效果。文章还分享了窗体设计和事件监听器的代码实现。
摘要由CSDN通过智能技术生成

接触java不满一个月,看厚厚的java入门简直要醉,故利用实例来巩固所学知识。
画板的实现其实从原理来说超级简单,可能一会儿就完成了。
但作为一名强迫症患者,要实现和win下面的画板一样的功能还是需要动下脑筋的。

画板雏形:
画板顾名思义,最主要功能就是要来画画的
这里写图片描述
Java里面的Graphics类里面提供了如下几种方法。
画圆画方画直线都不成问题,只需要提x1,x2,y1,y2即可。
在窗体上加个监听器,在mousePressed时用getX()和getY()获取x1,y1,在mouseReleased时用getX()和getY()获取x2,y2就完成了最简单的画板。

多边形:
多边形如何画呢,win下的画图板通过点击一处放置一个点,再点击一处放置另一个点,双击连接第一个点的和最后一个点完成绘制多边形。
利用以上思路,可以整理为,在mouseClicked时记录点的位置,若是第一个点,则要保存到一个固定的参数,若是其他点,则通过g.drawLine来连接上一个点和这个点,最后通过e.getClickCount()方法来获得是否双击来判断是否需要连接当前点和第一个点。

界面:
窗体的设计非常简单。其中按钮可以用循环来放置。加入监听器后可以通过e.getActionCommand()来获取按钮上的字符串。颜色按钮则可以通过新建一个JButton并利用getSource获取按下的Button,再利用JButton里面的getBackground获取颜色。
最后在本地p个图,利用下边界布局即可获得初级的界面。
最后再在可以绘画的位置加一个Panel,并从窗体获取graphics变成从该Panel获取,监听器改到该Panel下就可以保证画图的部分不会超过绘图区域了。
完成效果如下。
这里写图片描述

============华丽丽的分割线 强迫症从这里开始==============

画板的基本功能已经实现,但是作为一个强迫症怎么能够满足于鼠标拖拽时最后才凭空冒出来的一根线?

画板改进:
加入MouseMotionListener监听器
MouseMotionListener提供了两种方法
一个鼠标移动,一个是鼠标拖拽。
要想画直线拖拽鼠标的时候有一条实实在在的直线跟在后面跑,岂不是直接在mouseDragged时getx、y然后画出来就好了……于是就变成了这样:
这里写图片描述
初看觉得美美哒,而且它确确实实画了 不过每移动一点点位置就画了……
解决方案很容易就想到,每次画新的前,用背景色把上一条再画一遍不就好了。于是一条直线的拖拽就做好了。
然而当画第二条直线和第一条相交的时候……把第一条擦掉了是什么鬼!!!!!!!

想到两条解决方法~
1.把画板每个像素的涂色状态用二维数组来储存,然后每次画完一个图形都跟新一次数组。清空时把整个数组清0即可。该方法可能可以通过把现在画的通过BufferedImage中的createGraphyics形成graphycis tmp,然后画在tmp上,最后在读取图片数据来实现。不过貌似好麻烦……舍去。、
2.每画完一笔生成一个图片,然后把背景改成这个,然后再画……额 这个感觉还是有种治标不治本的感觉……舍去。
3.建立链表!!把所有的数据都保存在链表里面去!!然后每次画一笔就从头开始把刚才画的所有东西都画一遍。

由于是初学者,而且第一次在Java上实现链表,于是就按照自己对链表的理解,写了节点如下

package com.frame;

import java.awt.Color;
import java.awt.Graphics;

public class PaintedList {
    private String cmd;
    private DuoList PLi;
    private int x1, y1, x2, y2;
    private DuoList li;
    private PaintedList next;
    private Color color;

    public DuoList getPLi() {
        return PLi;
    }

    public void setPLi(DuoList pLi) {
        PLi = pLi;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public String getCmd() {
        return cmd;
    }

    public void setCmd(String cmd) {
        this.cmd = cmd;
    }

    public PaintedList getNext() {
        return next;
    }

    public void setNext(PaintedList next) {
        this.next = next;
    }

    public int getX1() {
        return x1;
    }

    public void setX1(int x1) {
        this.x1 = x1;
    }

    public int getY1() {
        return y1;
    }

    public void setY1(int y1) {
        this.y1 = y1;
    }

    public int getX2() {
        return x2;
    }

    public void setX2(int x2) {
        this.x2 = x2;
    }

    public int getY2() {
        return y2;
    }

    public void setY2(int y2) {
        this.y2 = y2;
    }

    public DuoList getLi() {
        return li;
    }

    public void setLi(DuoList li) {
        this.li = li;
    }

    public void paint(Graphics g) {
        g.setColor(color);
        if (cmd.equals("直线")) {
            g.drawLine(x1, y1, x2, y2);
        } else if (cmd.equals("椭圆")) {
            g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
        } else if (cmd.equals("矩形")) {
            g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
        } else if (cmd.equals("三角形")) {
            g.drawLine(x1, y1, x2, y2);
            g.drawLine(x2, y2, x2 - Math.abs(x2 - x1) * 2, y2);
            g.drawLine(x2 - Math.abs(x2 - x1) * 2, y2, x1, y1);
        } else if (cmd.equals("多边形")) {
            PLi = li;
            while (PLi.getnext() != null) {
                PLi.printline(g);
                PLi = PLi.getnext();
            }
        }
    }
}

多边形也用链表保存了所有的节点

package com.frame;

import java.awt.Graphics;

public class DuoList {
    private int x;
    private int y;
    private DuoList next;

    public int getx() {
        return this.x;
    }

    public int gety() {
        return this.y;
    }

    public void setx(int x) {
        this.x = x;
    }

    public void sety(int y) {
        this.y = y;
    }

    public void setnext(DuoList next) {
        this.next = next;
    }

    public DuoList getnext() {
        return this.next;
    }

    public void printline(Graphics g) {
        if (this.getnext() != null) {
            g.drawLine(x, y, next.getx(), next.gety());
        }
    }
}

值得注意的一点是,由于Java没有指针啥的,每次用完一个节点,在利用这个变量名之前要new一下,相当于malloc一个新的储存空间。

窗体的代码

package com.frame;

import java.awt.*;

import javax.swing.*;

public class Frame extends JFrame {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public Frame() {
        MouseAction m = new MouseAction();
        String[] kind = new String[] { "直线", "矩形", "椭圆", "三角形", "多边形", "清空" };
        Color[] color = { Color.black, Color.BLUE, Color.GREEN, Color.YELLOW };
        this.setSize(827, 647);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setBackground(Color.lightGray);
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        this.setLayout(new BorderLayout());

        ImageIcon im = new ImageIcon("image/bg.jpg");
        JLabel jla = new JLabel(im);
        this.getLayeredPane().add(jla, new Integer(Integer.MIN_VALUE));
        jla.setBounds(0, 0, 827, 627);
        JPanel jpanel = (JPanel) this.getContentPane();
        jpanel.setOpaque(false);

        JPanel west = new JPanel();
        west.setPreferredSize(new Dimension(189, 0));
        JPanel tmp1 = new JPanel();
        tmp1.setPreferredSize(new Dimension(189, 120));
        tmp1.setOpaque(false);
        JPanel tmp2 = new JPanel();
        tmp2.setPreferredSize(new Dimension(18, 0));
        tmp2.setOpaque(false);
        JPanel westcenter = new JPanel();
        westcenter.setOpaque(false);
        west.setLayout(new BorderLayout());
        west.add(tmp1, BorderLayout.NORTH);
        west.add(tmp2, BorderLayout.WEST);
        west.add(westcenter, BorderLayout.CENTER);
        for (int i = 0; i < kind.length; i++) {
            JButton jbu = new JButton(kind[i]);
            jbu.setBorderPainted(false);
            jbu.setFont(new Font("楷体", 15, 15));
            jbu.setPreferredSize(new Dimension(130, 40));
            jbu.setBackground(Color.orange);
            westcenter.add(jbu, BorderLayout.CENTER);
            jbu.addActionListener(m);
        }
        for (int i = 0; i < color.length; i++) {
            JButton jbu = new JButton();
            jbu.setBorderPainted(false);
            jbu.setBackground(color[i]);
            jbu.setPreferredSize(new Dimension(130, 40));
            westcenter.add(jbu, BorderLayout.CENTER);
            jbu.addActionListener(m);
        }
        west.setOpaque(false);
        this.add(west, BorderLayout.WEST);

        JPanel east = new JPanel();
        east.setPreferredSize(new Dimension(630, 0));
        this.add(east, BorderLayout.EAST);
        east.setOpaque(false);
        east.setLayout(null);

        JPanel board = new JPanel();
        board.setBounds(23, 28, 589, 567);
        // board.setBackground(Color.black);
        board.setOpaque(false);
        east.add(board);

        this.setVisible(true);

        Graphics g = board.getGraphics();
        board.addMouseListener(m);
        board.addMouseMotionListener(m);

        m.setGraphics(g);
        m.setJFrame(this);

    }
}

鼠标以及事件监听器的代码

package com.frame;

import java.awt.Color;
import java.awt.Graphics;
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;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MouseAction implements MouseListener, ActionListener, MouseMotionListener {
    private Graphics g;
    private int time = 0;
    private int x1, x2, y1, y2, oldx1, oldy1, curx1, cury1, flag = 0, x3, y3;
    private DuoList Li = new DuoList();
    private DuoList FLi = new DuoList();
    private DuoList PLi = new DuoList();
    private PaintedList ALLi = new PaintedList();
    private PaintedList FALLi = new PaintedList();
    private PaintedList PALLi = new PaintedList();
    public DuoList TMP;
    public PaintedList tmppaint = new PaintedList();
    public PaintedList tmppaint2 = new PaintedList();
    private int flag1 = 0;

    private String cmd = "直线";
    private Color color = Color.black;

    private JFrame frame;

    public void setJFrame(JFrame frame) {
        this.frame = frame;
    }

    public void setGraphics(Graphics g) {
        this.g = g;
    }

    public void mouseClicked(MouseEvent e) {
        TMP = new DuoList();
        tmppaint = new PaintedList();
        tmppaint2 = new PaintedList();
        if (cmd.equals("多边形")) {
            time = e.getClickCount();
            if (time == 2 && flag == 1) {
                flag = 0;
                g.drawLine(curx1, cury1, oldx1, oldy1);
                if (flag1 == 0) {
                    ALLi.setLi(Li);
                    ALLi.setColor(color);
                    ALLi.setCmd(cmd);
                    tmppaint.setX1(curx1);
                    tmppaint.setX2(oldx1);
                    tmppaint.setY1(cury1);
                    tmppaint.setY2(oldy1);
                    tmppaint.setColor(color);
                    tmppaint.setCmd("直线");
                    tmppaint.setNext(null);
                    ALLi.setNext(tmppaint);
                    FALLi = tmppaint;
                    flag1 = 1;
                    Li = new DuoList(); // 一定要new一个
                    FLi = new DuoList();
                    PLi = new DuoList();
                } else {
                    tmppaint.setLi(Li);
                    tmppaint.setCmd(cmd);
                    tmppaint.setColor(color);
                    tmppaint2.setX1(curx1);
                    tmppaint2.setX2(oldx1);
                    tmppaint2.setY1(cury1);
                    tmppaint2.setY2(oldy1);
                    tmppaint2.setColor(color);
                    tmppaint2.setCmd("直线");
                    tmppaint2.setNext(null);
                    FALLi.setNext(tmppaint);
                    tmppaint.setNext(tmppaint2);
                    FALLi = tmppaint2;
                    Li = new DuoList();
                    FLi = new DuoList();
                    PLi = new DuoList();
                }
            } else {
                if (flag == 0) {
                    flag = 1;
                    oldx1 = e.getX();
                    curx1 = oldx1;
                    oldy1 = e.getY();
                    cury1 = oldy1;
                    Li.setx(oldx1);
                    Li.sety(oldy1);
                    FLi = Li;
                    PLi = Li;
                    FLi.setnext(null);
                } else {
                    FLi.setnext(TMP);
                    curx1 = e.getX();
                    cury1 = e.getY();
                    TMP.setx(curx1);
                    TMP.sety(cury1);
                    TMP.setnext(null);
                    FLi = TMP;
                    g.setColor(color);
                }
            }
            x3 = curx1;
            y3 = cury1;
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    public void mousePressed(MouseEvent e) {
        x1 = e.getX();
        x3 = x1;
        y1 = e.getY();
        y3 = y1;
        g.setColor(color);
        System.out.println(x1 + " " + y1);

    }

    public void mouseReleased(MouseEvent e) {
        final PaintedList tmppaint = new PaintedList();
        x2 = e.getX();
        y2 = e.getY();
        if (cmd.equals("直线")) {
            g.drawLine(x1, y1, x2, y2);
        } else if (cmd.equals("椭圆")) {
            g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
        } else if (cmd.equals("矩形")) {
            g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
        } else if (cmd.equals("三角形")) {
            g.drawLine(x1, y1, x2, y2);
            g.drawLine(x2, y2, x2 - Math.abs(x2 - x1) * 2, y2);
            g.drawLine(x2 - Math.abs(x2 - x1) * 2, y2, x1, y1);
        }
        if (cmd.equals("多边形")) {

        } else {
            if (flag1 == 0) {
                ALLi.setX1(x1);
                ALLi.setX2(x2);
                ALLi.setY1(y1);
                ALLi.setY2(y2);
                ALLi.setCmd(cmd);
                ALLi.setColor(color);
                ALLi.setNext(null);
                FALLi = ALLi;
                flag1 = 1;
            } else {
                FALLi.setNext(tmppaint);
                tmppaint.setX1(x1);
                tmppaint.setX2(x2);
                tmppaint.setY1(y1);
                tmppaint.setY2(y2);
                tmppaint.setColor(color);
                tmppaint.setCmd(cmd);
                tmppaint.setNext(null);
                FALLi = tmppaint;
            }
            PALLi = ALLi;
            if (flag1 != 0) {
                while (PALLi != null) {
                    PALLi.paint(g);
                    PALLi = PALLi.getNext();
                }
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("")) {
            JButton jbu = (JButton) e.getSource();
            color = jbu.getBackground();
        } else {
            cmd = e.getActionCommand();
        }
        if (cmd.equals("清空")) {
            frame.repaint();
            flag = 0;
            flag1 = 0;
            cmd = "直线";
        }

    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (cmd.equals("直线")) {
            g.setColor(Color.WHITE);
            g.drawLine(x1, y1, x3, y3);
            x3 = e.getX();
            y3 = e.getY();
            g.setColor(color);
            g.drawLine(x1, y1, x3, y3);

        } else if (cmd.equals("椭圆")) {
            g.setColor(Color.WHITE);
            g.drawOval(Math.min(x1, x3), Math.min(y1, y3), Math.abs(x1 - x3), Math.abs(y1 - y3));
            x3 = e.getX();
            y3 = e.getY();
            g.setColor(color);
            g.drawOval(Math.min(x1, x3), Math.min(y1, y3), Math.abs(x1 - x3), Math.abs(y1 - y3));
        } else if (cmd.equals("矩形")) {
            g.setColor(Color.WHITE);
            g.drawRect(Math.min(x1, x3), Math.min(y1, y3), Math.abs(x1 - x3), Math.abs(y1 - y3));
            x3 = e.getX();
            y3 = e.getY();
            g.setColor(color);
            g.drawRect(Math.min(x1, x3), Math.min(y1, y3), Math.abs(x1 - x3), Math.abs(y1 - y3));
        } else if (cmd.equals("三角形")) {
            g.setColor(Color.WHITE);
            g.drawLine(x1, y1, x3, y3);
            g.drawLine(x3, y3, x3 - Math.abs(x3 - x1) * 2, y3);
            g.drawLine(x3 - Math.abs(x3 - x1) * 2, y3, x1, y1);
            g.setColor(color);
            x3 = e.getX();
            y3 = e.getY();
            g.drawLine(x1, y1, x3, y3);
            g.drawLine(x3, y3, x3 - Math.abs(x3 - x1) * 2, y3);
            g.drawLine(x3 - Math.abs(x3 - x1) * 2, y3, x1, y1);
        }
        PALLi = ALLi;
        if (flag1 != 0) {
            while (PALLi != null) {
                PALLi.paint(g);
                PALLi = PALLi.getNext();
            }
        }

    }

    @Override
    public void mouseMoved(MouseEvent e) {
        if (cmd.equals("多边形") && flag == 1) {
            g.setColor(Color.WHITE);
            g.drawLine(curx1, cury1, x3, y3);
            g.setColor(color);
            x3 = e.getX();
            y3 = e.getY();
            g.drawLine(curx1, cury1, x3, y3);
            while (PLi != null) {
                PLi.printline(g);
                PLi = PLi.getnext();
            }
            PLi = Li;
            PALLi = ALLi;
            if (flag1 != 0) {
                while (PALLi != null) {
                    PALLi.paint(g);
                    PALLi = PALLi.getNext();
                }
            }
        }

    }

}

主函数

package com.main;

import com.frame.Frame;

public class Game {
    public static void main(String[] args) {
        new Frame();
    }
}

后附一张background
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值