如何让代码等待GUI完成



我知道在Matlab方面也有类似的问题,但这对我的Java没有帮助。我正在为一个程序编写GUI,其中一个GUI帧的结果对于另一个GUI框架是必要的——我已经将我的问题简化为以下内容:

我有一个带有 JTextField 的GUI JFrame ,当按下按钮时,它会以字符串的形式返回字段的内容。

在staticmain方法的后面,这个字符串用于其他方法——尽管在本演示中,它只是被放入一个print语句中。

我遇到的问题是,代码没有等待GUI完成(也就是某人按下按钮并触发事件),然后再继续执行下一条语句——因此,在这个演示问题中,它会导致打印"null",而在我的更大问题中,会导致null传递给其他JFrame(并引发异常)。

我在网上学到的是,这是由于Swing的"多线程"性质——每次我创建Swing组件时,它都会在自己的线程中运行,以使其余的代码能够继续——然而,在这种情况下,我不希望其余的代码继续,我认为我想要的(我可能错了)是所有其他线程等待当前Swing线程完成,并给出一个可以在程序中进一步使用的结果。

我可以使用什么代码来使代码暂停,直到GUI的JButton被单击?

我知道解决这个问题的一个方法是将依赖代码"嵌套"在代码的 ActionListener 部分中,但在较大的项目中,这会给我带来大量的嵌套代码,这似乎不是一件好事。

主要方法的演示问题代码在这里:

public class Testing {
public static void main(String[] args) {
    Testing runningClass = new Testing();
    String message = null;
    JGetString getString = new JGetString();
    message = runningClass.initiateListener(getString);
    System.out.println(message); // How can I make this wait until getString
                                    // has closed?
}
private String initiateListener(JGetString window) {
    buttonListener listener = new buttonListener(window);
    window.addActionListener(listener);
    return listener.returning;
}
public class buttonListener implements ActionListener {
    JGetString getString;
    String returning;
    public buttonListener(JGetString getString) {
        this.getString = getString;
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        String returning = getString.returnString();
        this.returning = returning;
        getString.setVisible(false);
    }
}
}

扩展 JFrame 的GUI代码如下:

public class JGetString extends JFrame {
private JTextField textField;
private JButton btnGet = new JButton("Get");
public JGetString() {
    textField = new JTextField();
    getContentPane().add(textField, BorderLayout.CENTER);
    getContentPane().add(btnGet, BorderLayout.SOUTH);
    setVisible(true);
    pack();
}

public void addActionListener(ActionListener act) {
    btnGet.addActionListener(act);
}
public String returnString() {
    return textField.getText();
}

}

很抱歉有这么长的问题和大量的代码,谢谢!

正如Arvind在评论中指出的那样:当你想"等待GUI"时,一种常见的方法是对话框。特别是模式对话框。预定义的标准对话框可以使用JOptionPane的实用程序方法创建。更多信息,请访问http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html

对话框通常不是"真正的窗口"。例如,它在任务栏中没有表示形式。如果您想创建一个真正的JFrame,并等待它关闭,事情可能会变得有点麻烦:实际上,帧的创建应该在事件调度线程上完成。

因此,为了找到合适的解决方案,您应该清楚地知道哪个线程负责什么,哪个线程应该在哪个点等待哪个其他线程。

所谓"责任",我指的是每个班级所扮演的角色。例如:让ActionListener在这里发挥积极作用可能是一个可行的(可能更容易)解决方案。ActionListener可以调用主类中的一个方法,并将字符串传递给该方法。这将允许主线程和事件调度线程之间的简单同步(可能,但最好不要,与synchronizedwait()notifyAll()同步

然而,另一个解决方案,其中ActionListener保持"被动",并且实际字符串仍然是从JGetString实例中获得的,在这里进行了概述:它引入了一个仅封装CountDownLatchWaiter类,从而允许等待按钮被按下。但是注意根据您的长期目标以及计划背后的总体结构和意图,可能会有更合适的解决方案。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.CountDownLatch;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class WaitForGUI
{
    public static void main(String[] args)
    {
        WaitForGUI waitForGUI = new WaitForGUI();
        String message = waitForGUI.getStringFromGUI();
        System.out.println(message); 
    }
    private JGetString getString = null;    
    private Waiter waiter;
    public WaitForGUI()
    {
        // Create the synchronization aid that will
        // allow waiting for the `JGetString` to 
        // be closed
        waiter = new Waiter();
        // Create the GUI on the Event Dispatch Thread
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                getString = new JGetString();
                ButtonListener listener = new ButtonListener(getString);
                getString.addActionListener(listener);
                getString.addActionListener(waiter);
            }
        });
    }
    // This method will block until the button in 
    // the `JGetString` was pressed.
    String getStringFromGUI()
    {
        waiter.waitFor();
        return getString.returnString();
    }

    private class ButtonListener implements ActionListener
    {
        JGetString getString;
        public ButtonListener(JGetString getString)
        {
            this.getString = getString;
        }
        @Override
        public void actionPerformed(ActionEvent e)
        {
            getString.setVisible(false);
        }
    }
    private static class Waiter implements ActionListener
    {
        private final CountDownLatch latch = new CountDownLatch(1);
        @Override
        public void actionPerformed(ActionEvent e)
        {
            latch.countDown();
        }
        void waitFor()
        {
            try
            {
                latch.await();
            }
            catch (InterruptedException e)
            {
                Thread.currentThread().interrupt();
            }
        }
    }
}
class JGetString extends JFrame
{
    private JTextField textField;
    private JButton btnGet = new JButton("Get");
    public JGetString()
    {
        textField = new JTextField();
        getContentPane().add(textField, BorderLayout.CENTER);
        getContentPane().add(btnGet, BorderLayout.SOUTH);
        setVisible(true);
        pack();
    }
    public void addActionListener(ActionListener act)
    {
        btnGet.addActionListener(act);
    }
    public String returnString()
    {
        return textField.getText();
    }
}

相关内容

  • 没有找到相关文章

最新更新