我正在编写一个程序,按顺序完成以下任务:
我为每个任务都有一个单独的类,以及一个按顺序调用每个对象的主类。
我的问题是主类在步骤1完成之前评估第2步。因为当主类调用对象2时用户尚未关闭JPanel,所以在第2步启动之前不会收集用户输入并且程序崩溃。
我需要的是一种向第2类发信号通知第1类中的JPanel已经关闭的方法。这样,在步骤1中收集了输入字段后,步骤2开始。
有没有办法让类1中的窗口关闭触发第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();
}
}