java - 仅在窗口在 Java 中不再可见后才读取值

标签 java multithreading swing

也许我只是不知道去哪里找或者不完全理解线程是如何工作的,但我有两个不同的 JFrames(J1、J2)。 J1 是主要的 JFrame,它有一个可以选择 J2 的下拉菜单。当这个 J2 变得可见时,我需要 J1 等到 J2 的 foobar 值变为 -1 以外的值。我曾尝试用几种不同的方法给这只猫剥皮,但都没有成功。

我现在正在尝试的...

// located in J1
J2 otherFrame = new J2();
....

private synchronized void getNum() {
    try {
        while (otherFrame.returnNum() == -1) wait();
    }
    catch (Exception e) {}
    Long myResult = otherFrame.returnNum();
    ...
}



// located in J2
public synchronized Long returnNum() {
    try {
        while (someNum == -1) wait();
    }
    catch (Exception e) {}
    notify();
    return someNum;
}

我确信这看起来很愚蠢,但我需要 J1 等到 J2 将值分配给 someNum。该值将在用户单击提交时分配。它没有完成这项工作。我在这里做错了什么(更重要的是),如果这是一个线程问题,我的线程概念在哪里失败了?

最佳答案

解决方案不是为第二个窗口使用 JFrame,而是使用模态 对话框,例如模态 JDialog。这正是构建此类顶级窗口的目的。

这个问题是人们应该避免编写扩展 JFrame 的 Swing 类的另一个原因,因为这样做会使编码人员陷入困境并限制他们的选择。更好的方法是创建扩展或构建以创建 JPanel 的类,因为这样 JPanel 可以根据需要放置在 JFrame 或模态 JDialog 中,或者放置在另一个 JPanel 中,或者交换在 CardLayout 中,或者...

请注意,除了一些差异外,JDialog 的使用与 JFrame 的使用非常相似。您应该将对调用窗口(这里是您的第一个 JFrame)的引用传递到对话框中,并且您应该使用使对话框成为模态的构造​​函数,但 API 可以帮助您完成所有这一切。

当您使模态窗口可见时,调用代码中的代码流停止,并且在 JDialog 不再可见之前不会恢复。届时您可以查询 JDialog 的组件以获取状态并在调用代码中使用它。


例如:

import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class DialogEg {
    private static void createAndShowGui() {

        // create JFrame for application
        JFrame frame = new JFrame("Dialog Eg");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new MainPanel());
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

@SuppressWarnings("serial")
class MainPanel extends JPanel {
    private JTextField valueField = new JTextField(5);

    public MainPanel() {
        valueField.setFocusable(false); // so user can't interact with it

        add(new JLabel("Value:"));
        add(valueField);
        add(new JButton(new GetValueAction("Get Value")));
    }

    private class GetValueAction extends AbstractAction {
        private SecondPanel secondPanel = new SecondPanel();

        public GetValueAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            // get JPanel's top level window
            Window win = SwingUtilities.getWindowAncestor(MainPanel.this);

            // create jdialog that is modal
            JDialog dialog = new JDialog(win, "Get Value", ModalityType.APPLICATION_MODAL);
            dialog.add(secondPanel);

            // so the submit button will be activated when enter pressed:
            dialog.getRootPane().setDefaultButton(secondPanel.getSubmitButton());
            dialog.pack();
            dialog.setLocationRelativeTo(win);
            dialog.setVisible(true); // **** code flow stops here

            // and resumes here once dialog is no longer visible
            int value = secondPanel.getSpinnerValue();
            valueField.setText("" + value);
        }
    }
}

@SuppressWarnings("serial")
class SecondPanel extends JPanel {
    private SpinnerModel spinModel = new SpinnerNumberModel(-1, -1, 100, 1);
    private JSpinner spinner = new JSpinner(spinModel);
    private JButton submitButton = new JButton(new SubmitAction("Submit"));

    public SecondPanel() {
        add(spinner);
        add(submitButton);
    }

    public int getSpinnerValue() {
        return (Integer) spinner.getValue();
    }

    public JButton getSubmitButton() {
        return submitButton;
    }

    private class SubmitAction extends AbstractAction {
        public SubmitAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            int value = getSpinnerValue();

            // get JPanel's top level window
            Window win = SwingUtilities.getWindowAncestor(SecondPanel.this);
            if (value < 0) {
                String msg = "Submitted value must cannot be negative. Please try again";
                JOptionPane.showMessageDialog(win, msg, "Invalid Entry", JOptionPane.ERROR_MESSAGE);
                spinner.requestFocusInWindow(); // bring focus back to spinner
            } else {
                spinner.requestFocusInWindow();
                win.dispose();  // get rid of dialog
            }
        }
    }
}

关于java - 仅在窗口在 Java 中不再可见后才读取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32618197/

相关文章:

java - 查询线程执行情况

java - 悬停时图像变化 Java

java - Json 对象或字符串中的 Json 完整响应

java - 避免不必要的检查

java - 多次调用函数或创建变量

java - 排序 JTable 除了最后一行

java - 当我调整大小或移动滚动条时,我的线条和椭圆消失了

java - 使用FileOutputStream下载多个文件

java - 多线程上传多个文件时面临空指针

java - 非主线程的图片不动