让java函数等待单击按钮直到它返回

时间:2016-05-17 14:35:17

标签: java multithreading swing user-interface event-handling

我试图在一个小代码生成器' -application中实现一个函数 showTexfieldSettingsDialouge(Map fields),将一个充满字符串的Hashmap作为输入,显示一个带有迭代创建的面板和文本字段的摇摆窗口,用于Hashmap中提到的每个键,并在单击按钮后返回填充了用户输入的Hashmap。

问题:要等待单击按钮,我必须创建一个ActionListener,它在一个新的(Swing-)线程中运行。 如何让函数等待ActionListener被触发,继续,写入输入然后返回?

为了更好的帮助,我可以发布我写的代码,直到现在:

public class GUIMacroHandler {

    //diverse other functions

    public HashMap<String, String> showTexfieldSettingsDialouge(Map<String, String> fields){

    JFrame mainFrame = new JFrame("Please fill every Textfield with the correct Data");
    Map<String, JLabel> labels = new HashMap<String, JLabel>();
    Map<String, JTextField> textfields = new HashMap<String, JTextField>();
    JPanel optionpanel = new JPanel(new GridLayout(fields.size(), 2, 10, 10));
    JSplitPane splitPane = new JSplitPane();
    JButton btnSubmit = new JButton("Submit");


    splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
    mainFrame.getContentPane().add(splitPane, BorderLayout.NORTH);
    splitPane.setTopComponent(optionpanel);
    splitPane.setBottomComponent(btnSubmit);

    for (Entry<String, String> entry : fields.entrySet()) {
        labels.put(entry.getKey(),new JLabel(entry.getKey() + ":"));
        textfields.put(entry.getKey(),new JTextField(entry.getValue());
        optionpanel.add(labels.get(entry.getKey()));
        optionpanel.add(textfields.get(entry.getKey()));
    }



    btnSubmit.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e)
        {
            //Can't do stuff here because the function needs to return after the button is clicked and not before
        }
    });   

    mainFrame.pack();
    mainFrame.setVisible(true);

    //TODO:

    //Wait for button to be clicked somehow

    //Fill the given values with the input of the text fields

    return fields;
    }
}

该函数在代码中被多次强制转换,并且被认为可以根据用户需要的值轻松更改任何给定的String / String HashMap。 F.E.像这样:

GUIMacroHandler guiMacroHandler = new GUIMacroHandler();
combatsettings = guiMacroHandler.showTexfieldSettingsDialouge(combatsettings);

我已经搜索了一段时间没有找到问题的解决方案,我会非常乐意提供帮助,谢谢! :d

修改 如果我只在代码中使用此函数一次,那么在Action执行语句中发布内容只会是一种可能的解决方案,但这里不会因为函数被迫等待点击按钮返回在实际代码中,gui窗口将使用Hashmap的输入创建,然后返回给定的Hashmap,代码将继续,没有用户输入,窗口仍然存在,等待按钮最终被点击到期,但没有使用用户更改的数据和代码将继续使用默认值,因为它不会等待用户输入。

1 个答案:

答案 0 :(得分:2)

如果您确定从某个线程调用此方法,则可以执行此类操作!= EDT。例如,像这样

public static String getFrameResult() throws InterruptedException {
    if (SwingUtilities.isEventDispatchThread()) {
        throw new IllegalStateException("Can't be called from EDT.");
    }
    ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
    SwingUtilities.invokeLater(() -> {
        JFrame frame = new JFrame("Hello");
        JButton button = new JButton("Done");
        button.addActionListener((ActionEvent e) -> {
            String result = "Done at : " + LocalDateTime.now();
            queue.offer(result);
            frame.dispose();
        });
        frame.add(button);
        frame.pack();
        frame.setVisible(true);
    });
    return queue.take();
}

这里的技巧是将结果存储在内存中,并通知调用线程它已被保存,以便它可以接受并返回它。 BlockingQueue效果很好,因为Java 8是CompletableFuture,甚至可以手动通过wait / notify和共享变量。