如果放置在 setVisible(true) 之后,JDialog 中的事件处理程序将不起作用

Event handler in JDialog not working if placed after setVisible(true)

这是一个有趣的问题,在我构建上一个 JDialog 时没有出现,尽管那个问题比这个复杂得多。无论如何,这是导致问题的代码。

public class Test extends JDialog{

private final JButton cancel, ok;
private final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 50, 5));

public Test(JFrame parent) {
    //Initialize the JDialog
    super(parent, "Select Chapters");
    setLayout(new BorderLayout());
    setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    setModalityType(JDialog.ModalityType.APPLICATION_MODAL);
    setSize(300, 300);
    setLocationRelativeTo(null);


    cancel = new JButton("Cancel");
    ok = new JButton("OK");
    buttonPanel.add(cancel);
    buttonPanel.add(ok);
    getContentPane().add(buttonPanel, BorderLayout.SOUTH);



    setVisible(true);

    cancel.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent ae) {
            dispose();
        }
    });


}}

以及主要方法

Test test = new Test(new JFrame());

我将事件侦听器放在构造函数中进行测试,但实际实现应该在另一个 class 中进行。这就是为什么这是一个问题。如果我将动作侦听器放在 setVisible(true) 之前,那么一切都会按预期进行。但我不能这样做,因为事件处理程序将在另一个 class 中实现。是什么导致了这个问题,我该如何解决?

您需要将 setVisible(true) 放在构造函数的末尾,因为对话框是模态的,在这种情况下,setVisible(true) 不会 return 直到您调用 setVisible(false)。

引用 Java 文档:https://docs.oracle.com/javase/7/docs/api/java/awt/Dialog.html#setVisible(boolean)

Notes for modal dialogs.

setVisible(true): If the dialog is not already visible, this call will not return until the dialog is hidden by calling setVisible(false) or dispose.

setVisible(false): Hides the dialog and then returns on setVisible(true) if it is currently blocked.

It is OK to call this method from the event dispatching thread because the toolkit ensures that other events are not blocked while this method is blocked.

Event handler in JDialog not working if placed after setVisible(true)

正确,因为 JDialog 是模态的,所以 setVisible() 之后的语句直到对话框关闭才执行。

在对话框可见之前,您没有理由不能将 ActionListener 添加到按钮。代码在单独的 class 中并不重要。您只需在创建按钮的 class 的构造函数中创建 class 的实例。

I put setVisible() in the other class after I implemented the listeners

你还是做错了。 setVisible() 应该在您的主要 class 中,您可以在其中设置对话框属性并创建所有组件并将组件添加到对话框中。

我不确定你为什么这样做。您的代码可以是这样的:

cancel = new JButton("Cancel");
cancel.addActionListener( new SomeActionListenerClass() );
...
setVisible( true );