Java - 我的动作事件不起作用

时间:2017-02-10 18:43:15

标签: java swing user-interface jframe

我正在学习Java和Swing,但我的JButton不起作用。

import javax.swing.JFrame;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Programma {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }

        catch (Exception e){
            e.printStackTrace();
        }


        JFrame frame = new JFrame("DIG");
        JPanel panel = new JPanel();
        JButton button = new JButton("Click Me");

        frame.setSize(400, 400);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        button.setBounds(100, 100, 130, 35);

        panel.add(button);
        frame.add(panel);

        button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub

                JLabel label = new JLabel("Hello World");
                label.setVisible(true);
                panel.add(label);

            }
        });

    }
}
  1. 框架和按钮是可见的,当我点击它时,坚果,标签不会出现。我该如何解决这个问题?

  2. 我是在JPanel,JButton等其他组件之前编写的,还是在代码末尾写这个:

    frame.setVisible(true);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  3. 有什么区别?

    顺便说一句,button.setBounds(100, 100, 130, 35)也不起作用。

2 个答案:

答案 0 :(得分:4)

我在您的代码中看到了一些问题:

  1. button.setBounds(100, 100, 130, 35);该行将被忽略,您不应该手动确定组件的位置。请参阅Null layout is evilWhy is it frowned upon to use a null layout in swing?,即使您没有使用空布局,也可以解释为什么您不应该手动确定组件的位置。

  2. 您已使用main方法运行程序中的所有内容,以后很难维护。

  3. 在您将所有元素添加到其中之前,您正在致电frame.setVisible(true),这会导致您出现随机问题。

  4. 您未在Event Dispatch Thread (EDT)上运行程序,可以使用以下代码启动程序来解决此问题,该代码将其置于EDT中。它被推荐为Swing不是线程安全的。

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Your constructor here
            }
        });
    }
    
  5. 您已使用setSize(...)设置JFrame的尺寸,而是调用frame.pack()并覆盖getPreferredSize()的{​​{1}}方法}。

  6. 完成上述所有操作后,您需要在JPanel上致电revalidate()repaint(),以便您的计划描绘其新状态。

    此程序遵循以上所有建议并生成以下输出(在点击之前和单击按钮3次之后),我的目的是不使图像如此之大,使GUI缩短(200 x 200而不是400 x 400)

    enter image description here enter image description here

    ActionListener
      

    我是否在像JPanel,JButton这样的其他组件之前写这个...或者我是否在代码末尾写了这个?

         

    frame.setVisible(真);      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

         

    有什么区别?

    尽管我在建议中回答了这个问题,不同之处在于,如果在将所有元素添加到框架之前调用import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class Programma { private JFrame frame; private JPanel panel; private JButton button; public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Programma().createAndShowGui(); } }); } public void createAndShowGui() { frame = new JFrame("DIG"); panel = new JPanel() { @Override public Dimension getPreferredSize() { return new Dimension(400, 400); } }; button = new JButton("Click Me"); panel.add(button); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JLabel label = new JLabel("Hello World"); panel.add(label); panel.revalidate(); panel.repaint(); } }); frame.add(panel); frame.pack(); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } } ,那么您会发现自己遇到一些随机问题,其中组件并非全部直到你将鼠标放在它们上面(或它们应该在哪里)才可见。 setVisibleframe.pack()应该是您的计划中要调用的最后一个,setVisible可以在开头或结尾,它不会影响,但我更喜欢最后也有它。

      

    button.setBounds(100,100,130,35);也不起作用。

    嗯,那是因为你使用了layout manager(这是正确的GUI方式)而不是frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);(你是不管怎样都不应该使用)(参见第1点)。

    修改

      

    frame.setSize();有什么区别?和frame.setpack()?

    如果您阅读了null-layout的{​​{3}}:

      

    使此窗口的大小适合其子组件的首选大小和布局。如果任一维度小于上一次调用setMinimumSize方法所指定的最小大小,则会自动放大窗口的最终宽度和高度。

    因此,它会计算pack()的最小尺寸,其中所有元素都是可见的,并且是首选尺寸,而JFrame只会设置窗口大小,但是如果放置{{1}例如,这将减少窗口大小,因此,这就是为什么你应该覆盖容器的setSize方法,所以它会计算它的首选大小,包括{的宽度{1}}或其他一些可以修改其大小的元素。请参阅docs(普遍的共识是

答案 1 :(得分:0)

当您向组件动态添加组件时,需要重新创建它。

这样做

panel.revalidate(); 

之后

panel.add(label);