JButton 在 JFrame 中响应,但在 JPanel 中不响应

JButton responds in JFrame, but not in a JPanel

我是 java 的新手,我正在尝试了解动作侦听器和按钮的工作原理。我发现,如果我将 JButton 直接放入我的 JFrame 对象中,我可以获得一个有效的 JButton。但是,如果我将它放在 JFrame within 的 JPanel 中,它不会响应。这是为什么?

Main.java

public class Main {
    private static Frame f = new Frame();
    public static void main(String[] args) {}
}

Frame.java

public class Frame extends JFrame {
    private final int WIDTH = 640, HEIGHT = 480;
    private Panel p = new Panel();

    Frame() {
        super("Java Program");   
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(WIDTH, HEIGHT);
        this.setLayout(null);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    public void paint(Graphics g) {
        super.paint(g);
        p.paintComponent(g);
    }
}

Panel.java

public class Panel extends JPanel {
    JButton b = new JButton("Button");

    Panel() {
        b.setBounds(0,  0, 200, 100);
        add(b);
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                b.setText("Pressed");
            }
        });
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        b.paint(g);
    }
}

我不是 Swing 专家,所以我无法真正解释为什么它不起作用。似乎在您的按钮上画了一个无响应的按钮。我稍微调整了一下,这里有一些修改以使其正常工作:

  • 将面板添加到框架:add(p);
  • 删除this.setLayout(null);行,好像把框架搞乱了
  • 要设置框架的大小,请使用 setPreferredSize:this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
  • 您还需要在 Frame 构造函数的末尾调用 pack()
  • 并且您需要从 Panel.paintComponent() 中删除 b.paint(g),这似乎是绘制 "unresponsive" 按钮的原因,(请参见答案).

  • 可选地,您可以从框架中删除 paint(),它只做 JFrame 的一个

这是修改后的工作版本:

class Frame extends JFrame {
    private final int WIDTH = 640, HEIGHT = 480;
    private Panel p = new Panel();

    Frame() {
        super("Java Program");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        this.setLocationRelativeTo(null);
        this.setVisible(true);

        // add the panel to the frame
        add(p);

        pack();
    }

}

class Panel extends JPanel {
    JButton b = new JButton("Button");

    Panel() {
        b.setBounds(0,  0, 200, 100);
        add(b);
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                b.setText("Pressed");
            }
        });
    }


    // You can also get rid of this method, 
    // I just leave it here to show that I removed the b.paint(g) line
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    }
}

如果您在 Panel.paintComponent() 中保留 b.paint(g),这就是相同代码显示的内容,您可以看到有 2 个按钮,角落里的那个不起作用。