一个类中的事件是否可以触发另一个类中的操作?

时间:2014-08-30 16:42:45

标签: java swing events event-handling mouseevent

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

  1. 从JPanel收集用户输入
  2. 使用输入将程序目录中的依赖项复制到新项目目录中
  3. 使用输入在项目目录中构建交互式图形
  4. 我为每个任务都有一个单独的类,以及一个按顺序调用每个对象的主类。

    我的问题是主类在步骤1完成之前评估第2步。因为当主类调用对象2时用户尚未关闭JPanel,所以在第2步启动之前不会收集用户输入并且程序崩溃。

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

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

2 个答案:

答案 0 :(得分:4)

  

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

正如鲍力斯蜘蛛所指出的,你应该使用模型对话框。你可能正在使用一个框架。您应该阅读Modality以了解其行为和功能。还需要一些时间来查看How to make Dialogs。简而言之,打开对话框的模态(默认情况下JOptionPane静态showXxx方法,可以JDialog通过setModalityType设置或通过constructor设置}),流程将“阻塞”直到对话框关闭。

以下是一个例子。对于这样一个简单的任务可能过于复杂(因为它可以通过JOptionPane轻松完成),但它显示了如何使用JDialog。看作ShowDialogActionListener类。在对话框关闭之前,对话框设置为可见,并且动作未在actionPerformed中继续,即从对话框中获取Input

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");

以上也会阻止流程执行。

答案 1 :(得分:0)

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

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

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

主要

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();
    }
}