Java简易绘图板

最近终于学到了Swing,做了个简易画板。先完成自由绘制的功能,然后添加一堆按钮并加上相应的功能。


想加一个撤消上一步操作的功能,但是想不到应该怎么实现。

换背景色是用重新填充整块画布的方式来完成,这样会把画布上的所有内容清空,该如何在不影响已有内容的情况下,更换背景色呢?不知道有没有类似PhotoShop里的图层的组件。

总结出以下两点收获:

1.Image默认背景色是黑色,Graphics默认背景色是白色。

2.JToolBar和JPopupMenu都可以使用add(Action a)的方法添加一个按钮,但是JPanel就不行,只能把Action当作事件监听器添加。


另外推荐大家使用Sublime Text,体积小巧,功能强大。我选了自带的Solarized(Dark)主题,另外装了个Monaco字体和MacType字体渲染程序,界面非常漂亮。

刚用没多久,有两个功能非常实用。

一是分屏浏览+克隆,如下图,写界面的时候看变量名非常方便。



二是定位。cmd调试代码时会提示哪一行出现什么错误,这时回到Sublime Text,按下Ctrl+G,输入行数直达。



以下是我搜集的Sublime Text 3下载地址和使用技巧,其中破解版集成了中文补丁了很多插件。

Sublime Text3下载


最后附上程序代码


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

public class Test{
    //窗口
    private JFrame f = new JFrame("绘图板");
    //区域大小
    private final int WIDTH = 600;
    private final int HEIGHT = 600;
    //上一次鼠标坐标
    private int preX;
    private int preY;
    //按下鼠标时的坐标
    private int startX;
    private int startY;
    //画布
    MyCanvas drawArea = new MyCanvas();
    //画图用的image
    BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    //重写Graphics中的画矩形方法
    Graphics g = image.getGraphics();
    //前景色默认红,背景色默认白
    private Color foreColor = new Color(255, 0, 0);
    private Color backColor = new Color(255, 255, 255);
    //画笔,标记执行何种绘画模式
    //画笔的值均为四字符的小写字母
    private String brush = "free";

    //上方工具栏
    private JPanel p = new JPanel();
    private JButton lineButton = new JButton("直线");
    private JButton rectButton = new JButton("矩形");
    private JButton circButton = new JButton("圆形");
    private JButton freeButton = new JButton("自由绘制");
    private JButton foreButton = new JButton("前景色");
    private JButton backButton = new JButton("背景色");
    private JButton clearButton = new JButton("清空画布");
    //右键菜单,功能与工具栏上的按钮一模一样
    private JPopupMenu popMenu = new JPopupMenu("画图选项");

    //添加清空按钮
    //AbstractAction是Action接口的实现类,故不须重写所有方法
    //按钮和右键菜单都使用这个Action
    //JPanel不能使用JPanel.add(Action)来创建Button
    //按钮全要做到右键菜单上,所以每个按钮单独一个Action
    Action clearDrawArea = new AbstractAction("清空画布"){
        public void actionPerformed(ActionEvent e){
            //调用画布初始化方法,即完成清空画布
            imageInit();
        }
    };

    //按下按钮的事件监听器
    Action drawLine = new AbstractAction("直线"){
        public void actionPerformed(ActionEvent e){
            brush = "line";
        }
    };
    Action drawRect = new AbstractAction("矩形"){
        public void actionPerformed(ActionEvent e){
            brush = "rect";
        }
    };
    Action drawCirc = new AbstractAction("圆形"){
        public void actionPerformed(ActionEvent e){
            brush = "circ";
        }
    };
    Action drawFree = new AbstractAction("自由绘制"){
        public void actionPerformed(ActionEvent e){
            brush = "free";
        }
    };
    Action chooseForeColor = new AbstractAction("前景色"){
        public void actionPerformed(ActionEvent e){
            foreColor = chooseColor();
        }
    };
    Action chooseBackColor = new AbstractAction("背景色"){
        public void actionPerformed(ActionEvent e){
            backColor = chooseColor();
            imageInit();
        }
    };

    //初始化
    private void init(){
        drawArea.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        f.add(drawArea);

        //组合按钮
        lineButton.addActionListener(drawLine);
        rectButton.addActionListener(drawRect);
        circButton.addActionListener(drawCirc);
        freeButton.addActionListener(drawFree);
        foreButton.addActionListener(chooseForeColor);
        backButton.addActionListener(chooseBackColor);
        clearButton.addActionListener(clearDrawArea);
        p.add(lineButton);
        p.add(rectButton);
        p.add(circButton);
        p.add(freeButton);
        p.add(foreButton);
        p.add(backButton);
        p.add(clearButton);
        f.add(p, BorderLayout.NORTH);

        //组合右键菜单
        popMenu.add(drawLine);
        popMenu.add(drawRect);
        popMenu.add(drawCirc);
        popMenu.add(drawFree);
        popMenu.addSeparator();
        popMenu.add(chooseForeColor);
        popMenu.add(chooseBackColor);
        popMenu.addSeparator();
        popMenu.add(clearDrawArea);
        drawArea.setComponentPopupMenu(popMenu);

        //image初始化
        imageInit();

        //按下鼠标时记录坐标
        drawArea.addMouseListener(new MouseAdapter(){
            public void mousePressed(MouseEvent e){
                startX = e.getX();
                startY = e.getY();
            }
        });

        //拖曳鼠标时绘画
        drawArea.addMouseMotionListener(new MouseMotionAdapter(){
            public void mouseDragged(MouseEvent e){  
                switch (brush){
                    case "free":
                        if((preX > 0) && (preY > 0)){                    
                            g.setColor(foreColor);
                            g.drawLine(preX, preY, e.getX(), e.getY());
                        }
                        drawArea.repaint();
                        setPreXY(e);
                        break;
                    case "line":      
                        //如果鼠标移动,则撤消原来的直线
                        //以背景色画该直线模拟取消      
                        if(((e.getX() != preX)&&(preX != -1)) || ((e.getY() != preY)&&(preY != -1))){
                            g.setColor(backColor);
                            g.drawLine(startX, startY, preX, preY);
                        }            
                        g.setColor(foreColor);
                        g.drawLine(startX, startY, e.getX(), e.getY());
                        setPreXY(e);
                        drawArea.repaint();
                        break;
                    case "rect":
                        if(((e.getX() != preX)&&(preX != -1)) || ((e.getY() != preY)&&(preY != -1))){
                            g.setColor(backColor);
                            myDrawRect(startX, startY, preX, preY);
                        }
                        g.setColor(foreColor);
                        myDrawRect(startX, startY, e.getX(), e.getY());
                        setPreXY(e);
                        drawArea.repaint();
                        break;
                    case "circ":
                        if(((e.getX() != preX)&&(preX != -1)) || ((e.getY() != preY)&&(preY != -1))){
                            g.setColor(backColor);
                            myDrawOval(startX, startY, preX, preY);
                        }
                        g.setColor(foreColor);
                        myDrawOval(startX, startY, e.getX(), e.getY());
                        setPreXY(e);
                        drawArea.repaint();
                        break;
                        
                        

                }  
                
                
            }
        });
        //松开鼠标时preX、preY复位
        drawArea.addMouseListener(new MouseAdapter(){
            public void mouseReleased(MouseEvent e){
                preX = -1;
                preY = -1;
            }
        });
        


        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.pack();
        f.setVisible(true);
    }

    //选择颜色对话框
    private Color chooseColor(){
        //显示有模式的颜色选取器,在隐藏对话框之前一直阻塞
        return JColorChooser.showDialog(drawArea, "请选择画笔颜色",foreColor);
        
    }


    //画布初始化
    private void imageInit(){
        //image初始是黑色,填充白色背景
        g.setColor(backColor);
        g.fillRect(0,0,WIDTH, HEIGHT);
        drawArea.repaint();
    }

    //preX,preY复位
    private void setPreXY(MouseEvent e){
        preX = e.getX();
        preY = e.getY();
    }

    //自定义画矩形,起始点有可能在右下角,则须先排序再画
    private void myDrawRect(int a, int b, int c, int d){
        //根据(a,b),(c,d)两点画矩形,求出左上角顶点的坐标
        //宽和高是固定的|a-c|和|b-d|
        //罗列四种情况并计算得出如下算法
        g.drawRect(a<c?a:c, b<d?b:d, Math.abs(a-c), Math.abs(b-d));
    }
    //自定义画圆,起始点有可能在右下角,则须先排序再画
    private void myDrawOval(int a, int b, int c, int d){
        //根据(a,b),(c,d)两点画矩形,求出左上角顶点的坐标
        //宽和高是固定的|a-c|和|b-d|
        //罗列四种情况并计算得出如下算法
        g.drawOval(a<c?a:c, b<d?b:d, Math.abs(a-c), Math.abs(b-d));
    }
    
    


    //自定义画布,继承自JPanel,重写Paint方法
    private class MyCanvas extends JPanel{
        public void paint(Graphics g){
            g.drawImage(image, 0,0,null);
            
        }
    }

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



  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值