按下按钮时无法渲染矩形

Having troubles rendering rectangle on button press

我正在尝试通过按下按钮在面板中添加一个 Rectangle,然后用另一个按钮将其删除。它应该可以工作,但它不渲染任何东西,我完全不知道为什么。

谁能解释我做错了什么,并给我一些好的提示,我可以用我的代码改进什么?

public class GUI extends JPanel {

    public static boolean isRecVisible = false;

    public static void main(String[] args) {
        createGui();
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        super.paintComponent(g);
        g2d.drawRect(10, 10, 200, 200);
    }

    public static void createGui() {

        int frameWidth = 550;
        int frameHeight = 400;

        int buttonWidth1 = 250;
        int buttonHeight1 = 30;

        int buttonWidth2 = 500;
        int buttonHeight2 = 30;

        int displayWidth = frameWidth - 20;
        int displayHeight = frameHeight - 105;

        GUI drawRec = new GUI();

        JFrame f = new JFrame("Rectangle");
        JPanel p = new JPanel();
        JPanel display = new JPanel();
        JButton addRec = new JButton("Add Rectangle");
        JButton removeRec = new JButton("Remove Rectangle");
        JButton colorRec = new JButton("Color Rectangle");

        f.add(p);
        p.add(addRec);
        p.add(removeRec);
        p.add(colorRec);
        p.add(display);

        display.setBackground(Color.LIGHT_GRAY);

        f.setSize(frameWidth, frameHeight);
        f.setLocationRelativeTo(null);
        f.setResizable(false);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

        display.setBounds(frameWidth / 2 - displayWidth / 2, 10, displayWidth, displayHeight);
        addRec.setBounds(frameWidth / 2 - buttonWidth1 / 2 - 250 / 2, frameHeight - 85, buttonWidth1, buttonHeight1);
        removeRec.setBounds(frameWidth / 2 - buttonWidth1 / 2 + 250 / 2, frameHeight - 85, buttonWidth1, buttonHeight1);
        colorRec.setBounds(frameWidth / 2 - buttonWidth2 / 2, frameHeight - 60, buttonWidth2, buttonHeight2);

        addRec.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (isRecVisible == false) {
                    isRecVisible = true;
                    display.add(drawRec);
                    display.repaint();
                    System.out.println("Rectangle has been drawn!");

                } else {
                    System.out.println("Rectangle has already been drawn!");
                    return;
                }
            }
        });

        removeRec.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (isRecVisible == true) {
                    isRecVisible = false;
                    System.out.println("Rectangle has been removed!");

                } else {
                    System.out.println("Rectangle has already been removed");
                    return;
                }
            }
        });
    }
}
display.add(drawRec);
display.repaint();

当您向可见框架添加(或删除)组件时,基本逻辑是:

display.add(...);
display.revalidate();
display.repaint(); // sometimes needed

revalidate() 是关键方法,因为它调用布局管理器,因此可以设置组件的 size/location。

但是,这仍然无法解决问题,因为您的自定义面板没有首选尺寸,因此您的组件没有任何可绘制的东西。

您需要将自定义面板的 getPreferredSize() 方法覆盖为 return 自定义组件的首选大小。因此,在您的情况下,您可以将首选大小设置为 (220, 220),以便矩形在面板中居中。

阅读 Custom Painting 上的 Swing 教程部分以获取更多信息和完整的工作示例。

注意:本教程示例还将向您展示如何更好地构建代码以确保在事件调度线程上创建 GUI。

与其添加或删除组件,不如在构造中添加自定义绘制的面板,并使用 isRecVisible 布尔值作为标记来测试绘制矩形。

如下所示:

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

public class GUI extends JPanel {

    public static boolean isRecVisible = false;

    public static void main(String[] args) {
        createGui();
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        super.paintComponent(g);
        if (isRecVisible) {
            g2d.drawRect(10, 10, 200, 200);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(600,400);
    }

    public static void createGui() {
        int frameWidth = 550;
        int frameHeight = 400;

        GUI drawRec = new GUI();
        drawRec.setBackground(Color.LIGHT_GRAY);

        JFrame f = new JFrame("Rectangle");
        JPanel p = new JPanel();
        JButton addRec = new JButton("Add Rectangle");
        JButton removeRec = new JButton("Remove Rectangle");
        JButton colorRec = new JButton("Color Rectangle");

        f.add(p, BorderLayout.PAGE_START);
        p.add(addRec);
        p.add(removeRec);
        p.add(colorRec);
        f.add(drawRec);

        f.setSize(frameWidth, frameHeight);
        f.setLocationRelativeTo(null);
        f.setResizable(false);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

        addRec.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                isRecVisible = true;
                drawRec.repaint();
            }
        });

        removeRec.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                isRecVisible = false;
                drawRec.repaint();
            }
        });
    }
}