【问题标题】:Mock MSPaint program paints previous strokes instead of only the current stroke in java模拟 MSPaint 程序在 java 中绘制以前的笔画而不是仅绘制当前笔画
【发布时间】:2021-01-28 09:32:31
【问题描述】:

我的问题: graphics2D 对象重新着色 ArrayList 中的每个点。当我改变颜色时,我将如何做到这一点,它不会改变以前的颜色?我的猜测是改变 for 循环在 PaintApp 中的交互方式,但我不确定我应该做什么。感谢您的帮助!

我的代码:

PaintApp.java

package paint;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PaintApp extends JPanel {

    private List<List<Point>> points;
    private JFrame frame = new JFrame("Sketch MSPaint");
    private JMenuBar bar = new JMenuBar();
    private JMenu file = new JMenu("File");
    private JMenu colors = new JMenu("Colors");
    private JMenuItem quit = new JMenuItem("Quit");

    private JMenuItem red = new JMenuItem("Red");
    private JMenuItem blue = new JMenuItem("Blue");
    private JMenuItem green = new JMenuItem("Green");
    private JMenuItem orange = new JMenuItem("Orange");
    private JMenuItem pink = new JMenuItem("Pink");
    private JMenuItem cyan = new JMenuItem("Cyan");

    private JMenuItem clear = new JMenuItem("Clear");
    private boolean clearBoard = false, blackColor, redColor, blueColor, greenColor, orangeColor, pinkColor, cyanColor;

    
    
    public PaintApp(Dimension d) {
        this.setSize(d);
        this.setPreferredSize(d);

        points = new ArrayList<>();
        MouseAdapter ma = new MouseAdapter() {

            private List<Point> currentPath;

            @Override
            public void mousePressed(MouseEvent e) {
                currentPath = new ArrayList<>();
                currentPath.add(e.getPoint());

                points.add(currentPath);
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                Point dragPoint = e.getPoint();
                currentPath.add(dragPoint);
                repaint();
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                currentPath = null;
            }

        };

        addMouseListener(ma);
        addMouseMotionListener(ma);
    }

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.clearRect(0, 0, frame.getWidth(), frame.getHeight());

        for (List<Point> path : points) {
            Point from = null;
            for (Point p : path) {
                if (from != null) {
                    if (redColor) {
                        g2d.setColor(Color.red);
                    } else if (blueColor) {
                        g2d.setColor(Color.blue);
                    } else if (greenColor) {
                        g2d.setColor(Color.green);
                    } else if (orangeColor) {
                        g2d.setColor(Color.orange);
                    } else if (pinkColor) {
                        g2d.setColor(Color.pink);
                    } else if (cyanColor) {
                        g2d.setColor(Color.cyan);
                    } else {
                        g2d.setColor(Color.black);
                    }
                    g2d.drawLine(from.x, from.y, p.x, p.y);
                }
                from = p;
            }
        }
        g2d.dispose();
    }

    public void initBar() {
        bar.add(file);
        file.add(clear);
        clear.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                points = new ArrayList<>();
                repaint();
            }

        });
        file.add(quit);
        quit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                System.exit(0);

            }

        });

        bar.add(colors);
        colors.add(red);
        red.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                redColor = true;
                blueColor = false;
                greenColor = false;
                orangeColor = false;
                pinkColor = false;
                cyanColor = false;
                repaint();
            }

        });

        colors.add(orange);
        orange.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                redColor = false;
                blueColor = false;
                greenColor = false;
                orangeColor = true;
                pinkColor = false;
                cyanColor = false;
                repaint();

            }

        });

        colors.add(blue);
        blue.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                redColor = false;
                blueColor = true;
                greenColor = false;
                orangeColor = false;
                pinkColor = false;
                cyanColor = false;
                repaint();
            }

        });

        colors.add(green);
        quit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                redColor = false;
                blueColor = false;
                greenColor = true;
                orangeColor = false;
                pinkColor = false;
                cyanColor = false;
                repaint();

            }

        });

        colors.add(pink);
        quit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                redColor = false;
                blueColor = false;
                greenColor = false;
                orangeColor = false;
                pinkColor = true;
                cyanColor = false;
                repaint();

            }

        });

        colors.add(cyan);
        quit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                redColor = false;
                blueColor = false;
                greenColor = false;
                orangeColor = false;
                pinkColor = false;
                cyanColor = true;
                repaint();

            }

        });

        frame.setJMenuBar(bar);

    }

    public void show() {
        frame.add(this);
        initBar();
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

Main.java

package paint;

import java.awt.Dimension;

public class Main {
    public static void main(String[] args) {
        
        PaintApp app = new PaintApp(new Dimension(700,700));
        
        app.show();
        
    }
}

【问题讨论】:

  • 您应该创建一个自定义对象,其中包含您要绘制的所有属性。在您的示例中,您的对象可能包含一个 Line 对象和您要绘制的对象的 Color。有关工作示例,请参阅:Custom Painting Approaches。它绘制“彩色矩形”,但概念是相同的。
  • 最终我确实想添加一个撤消按钮 - 在上面的链接中提出的建议。
  • 这是唯一的方法吗?我不太确定我应该在缓冲图像上绘画,正如下面的人所说,没有办法添加撤消按钮,对吗?
  • 该链接不建议使用缓冲图像方法。它提供了另一种方法,包括如何使用鼠标绘制矩形。
  • Abys,@camickr 提出的建议类似于我回答的第二部分,即避免使用 BufferedImage 的部分。请重新阅读他的第一条评论和我的回答。

标签: java swing arraylist graphics paint


【解决方案1】:

如果您不想为此提供“撤消”功能,我看到的最简单的解决方案是绘制到 BufferedImage,然后在 paintComponent 覆盖中显示相同的 BufferedImage(不是 paint -- 从不paint)。这样,之前绘制的线条将一直存在,直到您将 BufferedImage 替换为新实例。

否则,如果你绝对不能走这条路,那么创建一个新的自定义类,它包含一个Line2D 或其他 Shape 类型的对象和一个 Color,当用户绘制时创建这些对象,将它们存储到一个 List此类对象,然后在您的 (again) paintComponent 覆盖中使用它们进行绘制。这样,您将每条线(或其他形状)与颜色相关联,并且关联将持续存在。

如上所述,我还建议不要覆盖paint,而是覆盖paintComponent,因为如果您决定制作动画,后者允许自动双缓冲,而且您也不会冒险搞砸绘制组件的子组件和边框,当您覆盖 paint 时,您可能会这样做。当然,在覆盖中调用super.paintComponent(g) 方法,通常在第一行。

【讨论】:

  • 最终我确实想添加一个撤消按钮,那么下一个最佳解决方案是什么?
  • @AbysssCoder:见编辑。或者,如果您走第一条路线,您可以将旧图像保存到磁盘。
  • 老实说,我的一个朋友做过鼠标按下的事情,我隐约理解。那么我将如何按照您的建议进行操作?你能在不给我答案的情况下澄清更多吗?
  • @AbysssCoder:恐怕时间不早了,该睡觉了。您可能想与给您代码的朋友联系以获得更多解释。虽然我的理念是避免借用代码,而是借用从其他代码中收集的想法,然后根据这些想法编写自己的代码。即使我的代码不是很好,我也比只使用其他代码更好地理解它。这在未来可能对你很有效。不过祝你好运。
  • 请注意,您的某些代码看起来与我在这里看到的由 MadProgrammer 创建的代码相似,例如在 this answer 中。他是 Swing 天才,您最好搜索并充分研究他与此作业相关的答案。你会从他们身上学到很多,我知道我有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多