清除我的 jpanel 后我无法绘图

Posted

技术标签:

【中文标题】清除我的 jpanel 后我无法绘图【英文标题】:I am not able to draw after clear my jpanel 【发布时间】:2022-01-20 01:13:49 【问题描述】:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.border.BevelBorder;

public class Cliente extends JPanel 
    private JButton adelanteButton;
    private JButton undoButton;
    private JPanel panel1;
    private JPanel panelDibujo;

    private Rectangulo rectangulo = new Rectangulo();
    Originator originator;
    Caretaker caretaker;


    public static void main(String[] args) 
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Patron Memento");
        Cliente cliente = new Cliente();
        frame.setContentPane(cliente.panel1);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    

    @Override
    public void paintComponent(Graphics g) 
        super.paintComponent(g);
        for (Memento m : caretaker.history) 
            System.out.println("forcitooooooo");
            dibujar(m.getState(), Color.GREEN);
        
    

    public Cliente() 

        caretaker = new Caretaker();
        originator = new Originator();
        createUIComponents();
        undoButton.addActionListener(e -> 
            caretaker.anterior();
            panelDibujo.repaint();
        );

        panelDibujo.setBackground(Color.WHITE);
        panelDibujo.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));

        panelDibujo.addMouseListener(new MouseAdapter() 
            @Override
            public void mousePressed(MouseEvent e) 
                MousePressedEvent(e);
            

            @Override
            public void mouseReleased(MouseEvent e) 
                MouseReleasedEvent(e);
            

        );
    

    private void createUIComponents() 
    

    private void MousePressedEvent(MouseEvent e)
        rectangulo.setX1(e.getX());
        rectangulo.setY1(e.getY());
    

    private void MouseReleasedEvent(MouseEvent e)
        rectangulo.setX2(e.getX());
        rectangulo.setY2(e.getY());
        originator.setState(rectangulo);
        dibujar(rectangulo, Color.orange);
        caretaker.addMemento(originator.CreateMemento());
        rectangulo = new Rectangulo();
    

    public void dibujar(Rectangulo r, Color c) 
        Graphics g = panelDibujo.getGraphics();
        g.setColor(c);
        g.drawRect(r.getX1(), r.getY1(), r.getX2() - r.getX1(), r.getY2() - r.getY1());
        g.dispose();
    


您好,我正在通过使用 jpanel 并在内部绘制一些矩形来应用 memento 模式,现在我的代码在使用鼠标事件进行绘图方面工作正常,但问题是当我尝试撤消时。到目前为止,我的逻辑是清除 jpanel 并重做所有矩形减去最后一个。 但是在清除我的 jpanel 后不再绘制 :( 有人可以帮我修复它吗?谢谢

看守者.java

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Stack;

public class Caretaker 
    LinkedList<Memento> history;
    int indice;

    public Caretaker()
        history = new LinkedList<>();
        indice = 0;
    

    void addMemento(Memento m)
        if (history.size() == indice || history.isEmpty())
            indice++;
            history.add(m);
        else 
            indice = history.size()-1;
            history.subList(indice +1, history.size()).clear();
        
    

    Memento anterior()
        if (history.size() > 0)
            indice--;
            return history.removeLast();
        
        JOptionPane.showMessageDialog(null, "No hay mas wey!");
        return null;
    

    Memento siguiente()
        if (indice < history.size()+1)
            indice++;
            return history.get(indice+1);
        
        JOptionPane.showMessageDialog(null, "No hay mas wey!");
        return null;
    

    public void redibujar(JPanel f)
        Graphics g = f.getGraphics();

        for (Memento m: history) 
            g.drawRect(m.getState().getX1(), m.getState().getY1(), m.getState().getX2() - m.getState().getX1(), m.getState().getY2() - m.getState().getY1());
            g.dispose();
        

    

    public void clear()
        history.clear();
        indice = 0;
    

Memento.java

public class Memento 
    Rectangulo state;

    /*
    Constructor, unica manera de mandar/crear/guardar los datos
     */
    public Memento(Rectangulo state) 
        this.state = state;
    

    public Memento()
        state = new Rectangulo();
    

    Rectangulo getState()
        return state;
    

Originator.java

public class Originator 
    Rectangulo state;

    public void setState(Rectangulo rectangulo)
        this.state = rectangulo;
    

    public Memento CreateMemento()
        return new Memento(state);
    

    public void setMemento(Memento m) 
        setState(m.getState());
    

Rectangulo.java

import java.awt.*;

public class Rectangulo 
    private int x1;
    private int x2;
    private int y1;
    private int y2;

    

    Rectangulo()
    

    public Rectangulo(int x1, int x2, int y1, int y2) 
        this.x1 = x1;
        this.x2 = x2;
        this.y1 = y1;
        this.y2 = y2;
    

    public int getX1() 
        return x1;
    

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

    public int getX2() 
        return x2;
    

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

    public int getY1() 
        return y1;
    

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

    public int getY2() 
        return y2;
    

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

    public void draw(Graphics g)
        g.setColor(Color.orange);
        g.drawRect(this.getX1(), this.getY1(), this.getX2() - this.getX1(), this.getY2() - this.getY1());
    

【问题讨论】:

一个问题是这不是您在 Swing 中使用图形的方式。您不应该在组件上调用 .getGraphics() 并使用该 Graphics 对象。而是使用传递给您的 paintComponent 方法的那个。 您想引出什么确切行为? 请注意,鉴于您当前的代码,我们都无法重现您的程序的不当行为,因为我们无法编译或运行它。考虑将其压缩为重现您的问题的最小可运行代码,minimal reproducible example。 我添加了运行它所需的所有代码。感谢您的时间和帮助。 不。由于 GUI 中未初始化的对象(例如 undoButton 等),您的代码会引发 NullPointerException 【参考方案1】:

再一次,您的绘图不正确。您正在尝试使用从未添加到 GUI 中的 JPanel、客户端进行渲染,并且您正在尝试使用从该未渲染组件中提取的 Graphics 对象,从而使由此获得的 Graphics 对象短暂且不稳定。

相反,在paintComponent 方法中进行所有绘制。如果需要,您可以使用 BufferedImage 并在paintComponent 中绘制它,特别是如果您想要具有显示不同颜色的对象的图像,或者您可以使用您的List(这里是LinkedList,但ArrayList 可以)并在paintComponent 中绘制。例如,一些简单的事情:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;


public class Cliente2 extends JPanel 
    private static final int BI_WIDTH = 800;
    private static final int BI_HEIGHT = 650;
    private Rectangle drawingRect = null;
    // private java.util.List<Rectangulo> rectangulos = new ArrayList<>();
    List<Rectangulo2> rectangulos = new ArrayList<>();
    private JButton clearBtn = new JButton("Clear");

    public Cliente2() 
        setBackground(Color.WHITE);
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);

        clearBtn.addActionListener(e -> clear());
        add(clearBtn);
    

    private void clear() 
        rectangulos.clear();
        repaint();
    

    @Override
    public Dimension getPreferredSize() 
        return new Dimension(BI_WIDTH, BI_HEIGHT);
    

    @Override
    protected void paintComponent(Graphics g) 
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        if (drawingRect != null) 
            g2.setColor(Color.LIGHT_GRAY);
            g2.draw(drawingRect);
        

        for (Rectangulo2 rectangulo : rectangulos) 
            rectangulo.draw(g2);
        
    

    private class MyMouse extends MouseAdapter 
        private Point p0;

        @Override
        public void mousePressed(MouseEvent e) 
            p0 = e.getPoint();
        

        @Override
        public void mouseDragged(MouseEvent e) 
            drawingRect = createDrawingRect(e);
            repaint();
        

        private Rectangle createDrawingRect(MouseEvent e) 
            Point p1 = e.getPoint();
            int x = Math.min(p0.x, p1.x);
            int y = Math.min(p0.y, p1.y);
            int width = Math.abs(p0.x - p1.x);
            int height = Math.abs(p0.y - p1.y);
            return new Rectangle(x, y, width, height);
        

        @Override
        public void mouseReleased(MouseEvent e) 

            // lets create some random colors:
            float hue = (float) Math.random();
            float brightness = (float) Math.random();
            Color color = Color.getHSBColor(hue, 1f, brightness);

            Rectangulo2 rectangulo = new Rectangulo2(color, p0, e.getPoint());
            rectangulos.add(rectangulo);
            drawingRect = null;
            repaint();
        
    
    
    public static void main(String[] args) 
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Patron Memento");
        
        // Cliente cliente = new Cliente();
        // frame.setContentPane(cliente.panel1);
        
        frame.add(new Cliente2());
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    

class Rectangulo2 
    private static final Stroke STROKE = new BasicStroke(3f);
    private Color color;
    private Point p0, p1;

    public Rectangulo2() 
    

    public Rectangulo2(Color color, Point p0, Point p1) 
        super();
        this.color = color;
        this.p0 = p0;
        this.p1 = p1;
    

    public Color getColor() 
        return color;
    

    public Point getP0() 
        return p0;
    

    public Point getP1() 
        return p1;
    

    public void draw(Graphics g) 
        Graphics2D g2 = (Graphics2D) g.create();

        g2.setColor(color);
        int x = Math.min(p0.x, p1.x);
        int y = Math.min(p0.y, p1.y);
        int width = Math.abs(p0.x - p1.x);
        int height = Math.abs(p0.y - p1.y);
        g2.fillRect(x, y, width, height);

        g2.setStroke(STROKE);
        g2.setColor(Color.BLACK);
        g2.drawRect(x, y, width, height);
        g2.dispose();
    


【讨论】:

非常感谢,我是java新手,我从你的代码中学到了很多东西,一点点东西,使用你的代码我如何撤消最后一个矩形?

以上是关于清除我的 jpanel 后我无法绘图的主要内容,如果未能解决你的问题,请参考以下文章

为啥我释放左键后我的绘图消失了?

如何在 JPanel 中绘图? (摇摆/图形Java)

如何保存我的绘图? (基本绘画应用程序)

使用JPanel绘图使JScrollPanel动态调整大小

如何仅清除qyqt5中的图?

Qwt - 重新绘制不清除当前绘图