簡體   English   中英

從 Swing GUI 向 Java 程序返回值

[英]Returning value to Java program from Swing GUI

背景

我正在將此 GUI 作為另一個程序的插件編寫。 GUI 提示用戶輸入應在 window 關閉時返回給主程序的值(在本例中為測試器中的println語句)。

我當前的方法是在okButton上使用 ActionListener,單擊它時,將returnValue設置為文本字段中的文本,並關閉 window。

我已經通讀了文檔並嘗試搜索諸如“從 GUI 返回值”、“按下按鈕后返回字段值”之類的術語,但我還沒有找到與我的用例相關的任何內容。 我對 Java GUI 的經驗很少,因此我很有可能缺少執行此操作的內置方法。

司機class:

public class Tester {

    public static void main(String[] args) {

        TestWindow tw = new TestWindow();
        String ret = tw.run();
        System.out.println(ret);
    }
}

Window Class

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

public class TestWindow {
    JFrame jFrame = new JFrame();
    JTextField textField = new JTextField("", 10);
    JButton okButton = new JButton("OK");
    String returnValue = "defaultValue";

    public TestWindow() {
        jFrame.setSize(400, 400);
        textField.setBounds(50, 100, 200, 30);
        okButton.setBounds(50, 150, 200, 30);
        okButton.addActionListener(e -> {
            // Set returnValue field to textField value
            returnValue = textField.getText();
            // Dispose of JFrame
            jFrame.dispose();
        });
        jFrame.add(textField);
        jFrame.add(okButton);
        jFrame.setLayout(null);
    }

    public String run() {
        jFrame.setVisible(true);
        return textField.getText();
    }

}

當我使用調試器單步調試驅動程序 class 時,返回的值始終是“defaultValue”,或者是retValue的初始默認值。 此外, run方法后的打印語句會在 window 出現時立即運行,而不是在 GUI 退出后運行。

問題

單擊“確定”按鈕后,如何將此值返回給主程序? (我的實際程序返回 hashmap,其中包含在 UI 中設置的各種值,但出於 MCVE 的目的,我已將其簡化為文本字段)。

使用更多上下文進行編輯:我正在為 MagicDraw 編寫一個插件。 沒有我可以利用的現有 Swing UI。 用戶單擊 MagicDraw UI 中的按鈕,啟動我的插件。 最初該插件使用沒有 Swing UI 的硬編碼變量,這是它的擴展。 但是,根據我的理解,我的問題應該與此無關。

使用模態對話框,請參閱如何制作對話框以獲取更多詳細信息。

作為一個簡單的例子,你可以只使用JOptionPane ...

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        JTextField textField = new JTextField(10);
        textField.setText("Default value");
        JPanel contentPane = new JPanel();
        contentPane.add(new JLabel("Type something: "));
        contentPane.add(textField);

        JOptionPane.showMessageDialog(null, contentPane, "Type someting", JOptionPane.PLAIN_MESSAGE);

        System.out.println(textField.getText());
    }
});

另一種方法是實現某種可以在觸發ActionListener時調用的觀察者模式,但老實說, JOptionPane更簡單

我建議為回調編寫一個最小接口,例如:

interface StuffToDoWithDialog {
    // will be called once values for foo and bar are ready
    void doStuff(String foo, int bar);
}

並構建接口,以便在值准備就緒后調用此接口的傳入實例:

public static void showDialog(StuffToDoWithDialog callback) {
    SwingUtilities.invokeLater(() -> {
        // ... draw interface ...
        // ... and somewhere, once values are ready, call callback
        callback.doStuff(foo, bar);
    });
}

這使得測試變得非常簡單,並且您可以在需要時傳遞更復雜的行為:

public static void main(String ... args) {
    showDialog((foo, bar) -> {
        System.out.println("Foo is " + foo);
        System.out.println("Bar is " + bar);
    });
}

工作程序(另存為Example.java ):

import javax.swing.*;
import java.awt.*;

public class Example {

    interface StuffToDoWithDialog {
        void doStuff(String foo, int bar);
    }

    public static void main(String ... args) {
        showDialog((foo, bar) -> {
            System.out.println("Foo is " + foo);
            System.out.println("Bar is " + bar);
        });
    }

    private static JTextField addFormRowToPanel(JPanel panel, String label, int rowNum) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.ipadx = 2;
        gbc.gridx = 0;
        gbc.gridy = rowNum;
        panel.add(new JLabel(label), gbc);
        JTextField field = new JTextField();
        field.setPreferredSize(new Dimension(50, (int)field.getPreferredSize().getHeight()));
        gbc.gridx = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel.add(field, gbc);
        return field;
    }

    public static void showDialog(StuffToDoWithDialog callback) {
        SwingUtilities.invokeLater(() -> {
            // builds contents for dialog: two inputs with labels
            JPanel jp = new JPanel(new GridBagLayout());
            JTextField foo = addFormRowToPanel(jp, "String foo", 0);
            JTextField bar = addFormRowToPanel(jp, "Integer bar", 1);
            
            boolean valid = false;
            while ( ! valid) {
                // blocks while showing dialog
                JOptionPane.showMessageDialog(null, 
                    jp, "Input options", JOptionPane.PLAIN_MESSAGE);
                // checks results
               if (foo.getText() != null 
                    && bar.getText() != null 
                    &&  bar.getText().matches("[0-9]+")) {
                        valid = true;
                } else {
                    // complain: bad inputs
                    int rc = JOptionPane.showConfirmDialog(null, 
                        "Invalid inputs, try again or cancel?", "Error", 
                        JOptionPane.OK_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE);
                    if (rc == JOptionPane.CANCEL_OPTION) return;
                }
            }

            // returns results
            callback.doStuff(foo.getText(), Integer.parseInt(bar.getText()));
        });
    }    
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM