当我绘制另一个矩形时,如何保留我在 Jpanel 上绘制的矩形?

Posted

技术标签:

【中文标题】当我绘制另一个矩形时,如何保留我在 Jpanel 上绘制的矩形?【英文标题】:How to keep the rectangle that I drew on the Jpanel when I draw another rectangle? 【发布时间】:2021-05-21 23:48:33 【问题描述】:

我在 JAVA 中有这段代码,当我在面板上拖动鼠标时,它会像绘图应用程序一样绘制一个矩形。每次我单击并拖动以创建一个新矩形时,前一个矩形就会消失。我想知道是否有办法让它留在面板上。并且有多个矩形,就像 windows 上的绘图应用程序一样。


import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

    public class DrawRect extends JPanel 

        int x, y, x2, y2;

        public static void main(String[] args) 
            JFrame f = new JFrame("Draw Box Mouse 2");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setContentPane(new DrawRect());
            f.setSize(300, 300);
            f.setVisible(true);
        

        DrawRect() 
            x = y = x2 = y2 = 0; // 
            MyMouseListener listener = new MyMouseListener();
            addMouseListener(listener);
            addMouseMotionListener(listener);
        

        public void setStartPoint(int x, int y) 
            this.x = x;
            this.y = y;
        

        public void setEndPoint(int x, int y) 
            x2 = (x);
            y2 = (y);
        

        public void drawPerfectRect(Graphics g, int x, int y, int x2, int y2) 
            int px = Math.min(x,x2);
            int py = Math.min(y,y2);
            int pw=Math.abs(x-x2);
            int ph=Math.abs(y-y2);
            g.drawRect(px, py, pw, ph);
        

        class MyMouseListener extends MouseAdapter 

            public void mousePressed(MouseEvent e) 
                setStartPoint(e.getX(), e.getY());
            

            public void mouseDragged(MouseEvent e) 
                setEndPoint(e.getX(), e.getY());
                repaint();
            

            public void mouseReleased(MouseEvent e) 
                setEndPoint(e.getX(), e.getY());
                repaint();
            
        

        public void paintComponent(Graphics g) 
            super.paintComponent(g);
            g.setColor(Color.RED);
            drawPerfectRect(g, x, y, x2, y2);
        

    

【问题讨论】:

当然。将每个矩形保存在 java.awt.Rectangle 对象的 java.util.List 中。从列表中绘制矩形。 paintComponent 在每次面板需要更新时调用,替换面板的所有内容。您需要管理要绘制的对象列表。 【参考方案1】:

在编写 Swing 图形程序时要记住一些有用的事情:

paintComponent 每次调用时都会重新绘制整个组件,因此您需要绘制您想要出现的所有内容。您对Graphics 对象执行的操作只会持续到下一次调用paintComponentGraphics2DGraphics 更有能力。它使用浮点坐标、各种线条样式等绘制了很好的抗锯齿形状。 paintComponentGraphics 参数实际上始终是 Graphics2D 实例,您可以将其强制转换为一个实例。 组件的继承层次也是绘画层次,所以你需要在paintComponent方法的开头调用super.paintComponent(g)。有关详细信息,请参阅this question。

所以我对你的程序做了一些修改:

添加了一个字段List<Rectangle2D> rectangles 来记住用户创建的矩形。每次抬起鼠标按钮时,都会向此列表添加一个矩形。 添加了对super.paintComponent的调用 使用Graphics2D绘制矩形,线条风格更有趣(Stroke) 更改了您的 paintComponent 以绘制列表中的每个矩形,以及用户当前正在绘制的“橡皮筋”矩形。

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

public class DrawRect extends JPanel 

    int x, y, x2, y2;
    // this is the list of all the rectangles the user has drawn so far
    List<Rectangle2D> rectangles = new ArrayList<>();

    public static void main(String[] args) 
        JFrame f = new JFrame("Draw Box Mouse 2");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new DrawRect());
        f.setSize(300, 300);
        f.setVisible(true);
    

    DrawRect() 
        x = y = x2 = y2 = 0; //
        MyMouseListener listener = new MyMouseListener();
        addMouseListener(listener);
        addMouseMotionListener(listener);
    

    public void setStartPoint(int x, int y) 
        this.x = x;
        this.y = y;
    

    public void setEndPoint(int x, int y) 
        x2 = (x);
        y2 = (y);
    

    // this creates a new rectangle object instead of drawing one
    public Rectangle2D makePerfectRect(int x, int y, int x2, int y2) 
        int px = Math.min(x,x2);
        int py = Math.min(y,y2);
        int pw=Math.abs(x-x2);
        int ph=Math.abs(y-y2);
        return new Rectangle2D.Float(px, py, pw, ph);
    

    class MyMouseListener extends MouseAdapter 

        public void mousePressed(MouseEvent e) 
            setStartPoint(e.getX(), e.getY());
        

        public void mouseDragged(MouseEvent e) 
            setEndPoint(e.getX(), e.getY());
            repaint();
        

        public void mouseReleased(MouseEvent e) 
            setEndPoint(e.getX(), e.getY());
            // when the mouse is released, we add the current rectangle to our list
            rectangles.add(makePerfectRect(x,y,x2,y2));
            repaint();
        
    

    public void paintComponent(Graphics g) 
        // use Graphics2D, you can draw much nicer lines
        Graphics2D g2d = (Graphics2D) g;
        super.paintComponent(g);
        g.setColor(Color.RED);
        // draw the rectangle the user is currently drawing
        g2d.draw(makePerfectRect(x,y,x2,y2));
        g.setColor(Color.BLUE);

                Stroke oldStroke = g2d.getStroke();
        g2d.setStroke(new BasicStroke(4.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0.0f));
        for (Rectangle2D r : rectangles) 
            g2d.draw(r);
        
        g2d.setStroke(oldStroke); // restore the original Stroke
    


【讨论】:

以上是关于当我绘制另一个矩形时,如何保留我在 Jpanel 上绘制的矩形?的主要内容,如果未能解决你的问题,请参考以下文章

Java Swing:在 JPanel 的组件下绘制?

Kivy - 在文本周围绘制矩形

JTextFields 在 JPanel 上的活动绘图之上,线程问题

清除画布矩形(但保留背景)

单击按钮时,QT在另一个顶部绘制一个矩形

在 JFrame 中将图像绘制到 JPanel