-2

我正在做一个应该像 Paint 应用程序一样工作的 GUI。我当前的问题是为我的画线和画矩形按钮添加适当的功能。他们目前没有像我预期的那样工作。帮助将不胜感激。

我搜索了许多关于学习如何绘制形状的代码片段,但没有一个显示如何根据按钮是否激活它们来使它们工作,以及如何从画线切换到画矩形。

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

public class paintGUI extends JComponent {

    // Image in which we're going to draw
    private Image image;
    // Graphics2D object ==> used to draw on
    private Graphics2D g2;
    // Mouse coordinates
    private int currentX, currentY, oldX, oldY;

    public paintGUI() {
        setDoubleBuffered(false);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                // save coord x,y when mouse is pressed
                oldX = e.getX();
                oldY = e.getY();
            }
        });

        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                // coord x,y when drag mouse
                currentX = e.getX();
                currentY = e.getY();

                if (g2 != null) {
                    // draw line if g2 context not null
                    //g2.drawLine(oldX, oldY, currentX, currentY);

                    //Need to implement these to their button
                    //g2.drawRect(oldX, oldY, currentX, currentY);
                    //g2.fillRect(oldX, oldY, currentX, currentY);

                    // refresh draw area to repaint
                    repaint();
                    // store current coords x,y as olds x,y
                    oldX = currentX;
                    oldY = currentY;
                }
            }
        });
    }

    @Override
    protected void paintComponent(Graphics g) {
        if (image == null) {
            // image to draw null ==> we create
            image = createImage(getSize().width, getSize().height);
            g2 = (Graphics2D) image.getGraphics();

            // clear draw area
            clear();
        }

        g.drawImage(image, 0, 0, null);
    }

    // now we create exposed methods
    public void clear() {
        g2.setPaint(Color.white);
        // draw white on entire draw area to clear
        g2.fillRect(0, 0, getSize().width, getSize().height);
        g2.setPaint(Color.black);
        repaint();
    }

    public void thin() {
        g2.setStroke(new BasicStroke(3));
    }

    public void thick() {
        g2.setStroke(new BasicStroke(10));
    }

    public void red() {
        // apply red color on g2 context
        g2.setPaint(Color.red);
    }

    public void black() {
        g2.setPaint(Color.black);
    }

    public void magenta() {
        g2.setPaint(Color.magenta);
    }

    public void drawLine() {
        g2.drawLine(oldX, oldY, currentX, currentY);
    }

    public void drawRectangle() {
        g2.drawRect(oldX, oldY, currentX, currentY);
        g2.fillRect(oldX, oldY, currentX, currentY);

    }
}

class GUIPaint {

    JButton clearBtn, blackBtn, redBtn, magentaBtn, filledRectangleBtn, lineBtn, thinBtn, thickBtn;
    paintGUI paintGUI;
    ActionListener actionListener = e -> {
        if (e.getSource() == clearBtn) {
            paintGUI.clear();
        } else if (e.getSource() == thinBtn) {
            paintGUI.thin();
        } else if (e.getSource() == thickBtn) {
            paintGUI.thick();
        } else if (e.getSource() == blackBtn) {
            paintGUI.black();
        } else if (e.getSource() == redBtn) {
            paintGUI.red();
        } else if (e.getSource() == magentaBtn) {
            paintGUI.magenta();
        } else if (e.getSource() == filledRectangleBtn) {
            paintGUI.drawLine();
        } else if (e.getSource() == lineBtn) {
            paintGUI.drawRectangle();
        }
    };

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

    public void show() {
        // create main frame
        JFrame frame = new JFrame("Swing Paint");
        Container content = frame.getContentPane();
        // set layout on content pane
        content.setLayout(new BorderLayout());
        // create draw area
        paintGUI = new paintGUI();

        // add to content pane
        content.add(paintGUI, BorderLayout.CENTER);

        // create controls to apply colors and call clear feature
        JPanel controls = new JPanel();

        clearBtn = new JButton("Clear");
        clearBtn.addActionListener(actionListener);
        blackBtn = new JButton("Black");
        blackBtn.addActionListener(actionListener);
        redBtn = new JButton("Red");
        redBtn.addActionListener(actionListener);
        magentaBtn = new JButton("Magenta");
        magentaBtn.addActionListener(actionListener);

        lineBtn = new JButton("Line");
        lineBtn.addActionListener(actionListener);
        filledRectangleBtn = new JButton("Filled Rectangle");
        filledRectangleBtn.addActionListener(actionListener);

        thickBtn = new JButton("Thick Line");
        thickBtn.addActionListener(actionListener);
        thinBtn = new JButton("Thin Line");
        thinBtn.addActionListener(actionListener);

        controls.add(lineBtn);
        controls.add(filledRectangleBtn);
        controls.add(thinBtn);
        controls.add(thickBtn);
        controls.add(blackBtn);
        controls.add(redBtn);
        controls.add(magentaBtn);
        controls.add(clearBtn);

        // add to content pane
        content.add(controls, BorderLayout.NORTH);

        frame.setSize(800, 800);
        // can close frame
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // show the swing paint result
        frame.setVisible(true);
    }
}

如果我单击线条按钮以绘制线条,或者按下矩形按钮而不是绘制矩形,我需要程序正确响应。

4

1 回答 1

1

基本思想是让控件(按钮、鼠标)改变属性(颜色、形状、笔触、坐标)并调用重绘。
paintComponent使用这些属性来绘制正确的形状。
请注意您的代码的注释修改。
代码是一个文件mre:整个代码可以复制粘贴到GUIPaint.java并运行:

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import swing_tests.PaintGUI.SHAPE;

public class GUIPaint {

    private PaintGUI paintGUI;

    public void showGui() {

        JFrame frame = new JFrame("Swing Paint");
        Container content = frame.getContentPane();
        content.setLayout(new BorderLayout());
        paintGUI = new PaintGUI();
        content.add(paintGUI, BorderLayout.CENTER);

        // create controls to apply colors and call clear feature
        JPanel controls = new JPanel();

        //todo: reduce duplicate code by having a method that constructs
        //and adds a button
        //todo: use button groups where only one button can be selected 
        JButton clearBtn = new JButton("Clear");
        JButton blackBtn = new JButton("Black");
        JButton redBtn = new JButton("Red");
        JButton magentaBtn = new JButton("Magenta");
        JButton lineBtn = new JButton("Line");
        JButton filledRectangleBtn = new JButton("Filled Rectangle");
        JButton thickBtn = new JButton("Thick Line");
        JButton thinBtn = new JButton("Thin Line");

        //todo: register an Action listner to each button by using lambda
        //for example   clearBtn.addActionListener(e-> paintGUI.clear());
        ActionListener actionListener = e -> {
            if (e.getSource() == clearBtn) {
                paintGUI.clear();
            }else if (e.getSource() == thinBtn) {
                paintGUI.thin();
            } else if (e.getSource() == thickBtn) {
                paintGUI.thick();
            } else if (e.getSource() == blackBtn) {
                paintGUI.black();
            } else if (e.getSource() == redBtn) {
                paintGUI.red();
            } else if (e.getSource() == magentaBtn) {
                paintGUI.magenta();
            } else if (e.getSource() == filledRectangleBtn) {
                paintGUI.setShape(SHAPE.RECTANGLE);
            } else if (e.getSource() == lineBtn) {
                paintGUI.setShape(SHAPE.LINE);
            }
        };

        clearBtn.addActionListener(actionListener);
        blackBtn.addActionListener(actionListener);
        redBtn.addActionListener(actionListener);
        magentaBtn.addActionListener(actionListener);
        lineBtn.addActionListener(actionListener);
        filledRectangleBtn.addActionListener(actionListener);
        thickBtn.addActionListener(actionListener);
        thinBtn.addActionListener(actionListener);

        controls.add(lineBtn);
        controls.add(filledRectangleBtn);
        controls.add(thinBtn);
        controls.add(thickBtn);
        controls.add(blackBtn);
        controls.add(redBtn);
        controls.add(magentaBtn);
        controls.add(clearBtn);

        content.add(controls, BorderLayout.NORTH);
        frame.setSize(800, 800);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new GUIPaint().showGui());
    }
}

class PaintGUI extends JComponent {

    //states defined by enum
    enum SHAPE {RECTANGLE, LINE}

    private SHAPE shape; // store state
    private static final Color BACKGROUND_COLOR = Color.WHITE;
    private int startX, startY, endX, endY;  //shape coordinates
    private Color color = Color.BLACK;       //draw color
    private BasicStroke stroke = new BasicStroke(3); //draw stroke
    private boolean isClear = false;

    public PaintGUI() {

        setDoubleBuffered(false);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                //save coord x,y where mouse was pressed
                startX = e.getX();
                startY = e.getY();
                endX = startX; endY = startY;
                clear(); //clear draw board
            }

        });

        addMouseMotionListener(new MouseAdapter() {

            @Override
            public void mouseDragged(MouseEvent e) {
                    //update end coord as mouse dragged
                    endX = e.getX();
                    endY = e.getY();
                    repaint();  //keep repainting while drag lasts 
            }
        });
    }

    @Override
    protected void paintComponent(Graphics g) {

        Graphics2D g2 = (Graphics2D) g;
        // draw white on entire draw area to clear
        g2.setColor(BACKGROUND_COLOR);
        g2.fillRect(0, 0, getSize().width, getSize().height);
        if(isClear || shape == null){
            isClear = false;
            return;
        }

        //draw using color , stroke and shape attributes 
        g2.setColor(color);   
        g2.setStroke(stroke);

        switch (shape){
            case RECTANGLE:
                drawFilledRectangle(g2);
                break;
            case LINE:
                drawLine(g2);
                break;
            default:
                break;
        }
    }

    public void clear() {
        isClear = true;
        repaint();
    }

    public void drawLine(Graphics2D g2) {
        g2.drawLine( startX, startY, endX, endY);
        repaint();
    }

    public void drawFilledRectangle(Graphics2D g2) {
        //to allow rectangle dragged from bottom up and left to right
        //use min x and min y as origin
        int x = Math.min(startX, endX);
        int y = Math.min(startY, endY);
        int width = Math.abs(endX-startX);  //to account for negative width
        int height = Math.abs(endY-startY); //or height
        g2.fillRect(x,y,width,height);
    }

    public void thin() {
        setStroke(3);
    }

    public void thick() {
        setStroke(10);
    }

    public void setStroke(int width) {
        stroke  = new BasicStroke(width);
        repaint();
    }

    public void red() {
        setColor(Color.red);
    }

    public void black() {
        setColor(Color.black);
    }

    public void magenta() {
        setColor(Color.magenta);
    }

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

    void setShape(SHAPE shape) {
        this.shape = shape;
        clear();
    }
}

在此处输入图像描述

于 2019-09-01T17:03:09.417 回答