清除我的 jpanel 后我无法绘制

I am not able to draw after clear my jpanel

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 并在内部绘制一些矩形来应用纪念图案,现在我的代码可以正常使用鼠标事件进行绘制,但问题是当我尝试撤消时。到目前为止,我的逻辑是清除 jpanel 并重做所有矩形减去最后一个。 但是清除后我的 jpanel 不再绘制 :( 谁能帮我解决这个问题?谢谢

Caretaker.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());
    }
}

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

而是在 paintComponent 方法中进行所有绘制。如果需要,您可以使用 BufferedImage 并在 paintComponent 中绘制它,特别是如果您想要具有显示不同颜色的对象的图像,或者您可以使用您的列表(这里是 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();
    }

}