Java 一个类中的事件能否触发另一个类中的操作?

Java 一个类中的事件能否触发另一个类中的操作?,java,swing,events,event-handling,mouseevent,Java,Swing,Events,Event Handling,Mouseevent,我正在编写一个程序,按顺序完成以下任务: 从JPanel收集用户输入 使用输入将依赖项从程序目录复制到新的项目目录中 使用输入在项目目录中构造交互式图形 每个任务都有一个单独的类,还有一个按顺序调用每个对象的主类 我的问题是主类在步骤1完成之前评估步骤2。因为当主类调用对象2时,用户还没有关闭JPanel,所以在步骤2开始之前没有收集用户输入,程序崩溃 我需要的是一种向2类发出信号的方法,即1类中的JPanel已关闭。这样,在步骤1中收集输入字段后,步骤2开始 有没有办法让类1中的窗口关闭触发类

我正在编写一个程序,按顺序完成以下任务:

  • 从JPanel收集用户输入
  • 使用输入将依赖项从程序目录复制到新的项目目录中
  • 使用输入在项目目录中构造交互式图形
  • 每个任务都有一个单独的类,还有一个按顺序调用每个对象的主类

    我的问题是主类在步骤1完成之前评估步骤2。因为当主类调用对象2时,用户还没有关闭JPanel,所以在步骤2开始之前没有收集用户输入,程序崩溃

    我需要的是一种向2类发出信号的方法,即1类中的JPanel已关闭。这样,在步骤1中收集输入字段后,步骤2开始

    有没有办法让类1中的窗口关闭触发类2中的操作?如果没有,解决这个问题的最佳方法是什么

    “有没有办法让类1中的窗口关闭触发类2中的操作?如果没有,解决此问题的最佳方法是什么?”

    正如蜘蛛Boris所指出的,您应该使用一个模型对话框。你可能正在使用一个框架。你应该仔细阅读,了解它的行为和特点。也需要一些时间来看看。简而言之,打开对话框的模式(默认为静态
    showXxx
    方法,可通过或通过设置为
    JDialog
    ),流程将“阻塞”,直到对话框关闭

    下面是一个例子。对于这样一个简单的任务,它可能过于复杂了(因为它可以很容易地用
    JOptionPane
    完成),但它展示了如何使用
    JDialog
    。查看
    ShowDialogActionListener
    类。对话框被设置为可见,并且直到对话框关闭(即从对话框中获取
    输入时),流程才会在执行的操作中继续

    import java.awt.GridBagLayout;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    
    public class DialogDemo {
        private JFrame frame = new JFrame();
    
        public DialogDemo() {
            JButton button = new JButton("Open Dialog");
            button.addActionListener(new ShowDialogActionListener());
            frame.setLayout(new GridBagLayout());
            frame.add(button);
            frame.setSize(300, 300);
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }
    
        class ShowDialogActionListener implements ActionListener {
    
            @Override
            public void actionPerformed(ActionEvent e) {
                InputDialog dialog = new InputDialog(frame, true);
                System.out.println("Opened dialog.....");
    
                long start = System.currentTimeMillis();
                dialog.setVisible(true);
                System.out.println("Dialog closed after "
                        + (System.currentTimeMillis() - start) + " ms");
    
                Input input = dialog.getInput();
                ServiceOne service = new ServiceOne();
                service.serviceMethod(input);
            }
        }
    
        class ServiceOne {
            public void serviceMethod(Input input) {
                System.out.println(input.getInput());
            }
        }
    
        class InputDialog extends JDialog {
            private Input input;
    
            public InputDialog(JFrame parent, boolean modal) {
                super(parent, modal);
    
                JPanel panel = new JPanel(new GridLayout(0, 1));
                final JTextField field = new JTextField(20);
                JButton okButton = new JButton("OK");
                panel.add(field);
                panel.add(okButton);
    
                okButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        String text = field.getText();
                        input = new Input();
                        input.setInput(text);
                        InputDialog.this.dispose();
                    }
                });
    
                setLayout(new GridBagLayout());
                add(panel);
                setSize(250, 250);
                setLocationRelativeTo(parent);
            }
    
            public Input getInput() {
                return input;
            }
        }
    
        class Input {
            private String input = "default";
    
            public void setInput(String input) {
                this.input = input;
            }
    
            public String getInput() {
                return input;
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new DialogDemo();
                }
            });
        }
    }
    
    正如我早些时候所说,同样的事情也可以很容易地用

    String input = JOptionPane.showInputDialog("Enter a Message");
    

    上述操作也会阻止流的执行。

    在类之间传递事件的技巧是
    wait()
    notify()
    方法

    假设您正在执行
    main
    方法。在某个时刻,
    main
    调用另一个类,比如gui。在这里,您希望
    main
    暂停并等待gui中的某些事件完成,然后
    main
    继续执行其其余操作

    这是通过在两个类之间同步代码块并告诉
    main
    wait()
    直到gui通知它继续,
    notify()
    来实现的。例如:

    main

    public static void main(String[] args) throws Exception {
    
        GUI gui = new GUI();
    
        // Do some things
        doSomething();
        doSomthingElse();
    
        // Make sure we wait until gui input has been collected before proceeding
        synchronized(gui) {
            try {
                gui.wait();
            }
            catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    
        // Do some things using the gui input we've been waiting for        
        doSomeMoreThings();
    }
    
    gui

    // The gui method we want to synchronize
    public void collectInput() {
    
        synchronized(this) {
    
            // Collect fields
            name = nameField.getText();
            age = ageField.getText();
            date = dateField.getText();
    
            // Notify waiter that our business is complete  
            notify();
        }
    }
    

    您很可能是1)在EDT之外运行Swing组件,导致线程问题,或者2)没有使用模式对话。我阅读了线程方面的内容,我认为这可能是问题所在。我希望把事情划分开来,但我想我只能把它们放在一个类中。对于其他偶然发现这一点的人来说,EDT是事件调度线程,这里有一篇很好的文章:。我想你可能误解了我的问题。我运行了您提供的代码,它几乎与我的程序当前所做的完全相同--打开父窗口,单击父窗口中的按钮时打开弹出窗口,关闭弹出窗口时记录弹出窗口输入。我需要的是一种方法,然后与一个单独的类(调用父窗口的类)通信父窗口已关闭。否则,调用输入gui的类会在实际收集gui输入之前尝试执行其其余任务。通过一些代码可以更容易地说出您在说什么。请用一些相关的代码编辑您的帖子如果有简洁的方式向您展示一些代码,我会:)但我发现了——必须使用wait()和notify()。