Java 简单形状程序

Java Simple Shape Program

我正在尝试使用 GUI 制作这个简单的程序,一旦按下 JButton,它就会创建一个圆圈。我一直在研究这个,并试图弄清楚为什么这几个小时都不起作用。我在 Whosebug 上与有类似问题的人一起查看了类似的代码,但是,我仍然无法弄清楚。有人可以告诉我哪里出了问题以及为什么我不正确吗?谢谢你。

public class ColorShape {

    public static void main(String[] args) {

        CreatePanel c = new CreatePanel();
        c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        c.setSize(300, 450);
        c.setVisible(true);

    }
}

public class CreatePanel extends JFrame {

    private JButton DC;
    private BorderLayout layout;

    public CreatePanel() {
        super("Color-Shape");
        layout = new BorderLayout();
        setLayout(layout);

        DC = new JButton("Circle");
        DC.addActionListener(
                new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                DrawCirc circ = new DrawCirc();
                add(circ);
                repaint();
            }
        }
        );
        add(DC, BorderLayout.NORTH);

    }
}

public class DrawCirc extends JPanel {

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.cyan);
        g.fillOval(100, 100, 50, 50);

    }
}

那么,您的第一个问题是,DrawCirc 不提供尺寸提示,这意味着它的默认尺寸将为 0x0

public class DrawCirc extends JPanel {

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

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.cyan);
        g.fillOval(100, 100, 50, 50);
    }
}

此外,请记住,Graphics 上下文已翻译,因此 0x0 是组件的左上角。

第二个问题是,Swing 是惰性的。它允许您对 UI 进行一些更改,然后对它们进行批处理。这意味着当您完成 UI 更新后,您必须同时调用 revalidaterepaint 来触发布局和绘制过程

DC.addActionListener(
        new ActionListener() {
    public void actionPerformed(ActionEvent event) {
        DrawCirc circ = new DrawCirc();
        add(circ);
        revalidate();
        repaint();
    }
});

这两个问题并不少见。您应该花更多时间了解布局管理系统,因为它会让您的生活更简单 ;)

更改组件层次结构后,将 repaint() 更改为 revalidate()。您会注意到,如果您调整 window 的大小,您当前的版本会绘制圆圈,因为这会使布局重新生效。

来自文档:

Revalidates the component hierarchy up to the nearest validate root. This method first invalidates the component hierarchy starting from this component up to the nearest validate root. Afterwards, the component hierarchy is validated starting from the nearest validate root. This is a convenience method supposed to help application developers avoid looking for validate roots manually. Basically, it's equivalent to first calling the invalidate() method on this component, and then calling the validate() method on the nearest validate root.