我正在编写一个程序,按顺序完成以下任务:
- 从JPanel收集用户输入
- 使用输入将依赖项从程序目录复制到新的项目目录中
- 使用输入在项目目录中构造交互式图形
我为每个任务都有一个单独的类,还有一个按顺序调用每个对象的主类。
我的问题是,主类在步骤1完成之前评估步骤2。因为当主类调用对象2时,用户还没有关闭JPanel,所以在步骤2开始之前没有收集用户输入,程序崩溃。
我需要的是向类2发出信号,表明类1中的JPanel已经关闭。通过这种方式,步骤2在步骤1中收集了输入字段之后开始。
有没有办法让类1中的窗口关闭触发类2中的操作?如果没有,解决这个问题的最佳方法是什么?
"有没有办法让1类中的窗口关闭触发2类中的操作?如果没有,解决这个问题的最佳方法是什么?"
正如Boris the Spider所指出的,你应该使用一个模型对话框。你可能在用相框。你应该阅读模态来了解它的行为和特征。还要花一些时间来看看如何制作对话框。简而言之,打开对话框的模态(这是JOptionPane静态showXxx
方法的默认值,可以通过setModalityType
或通过构造函数在JDialog
上设置),流将"阻塞",直到对话框关闭。
下面是一个例子。对于这样一个简单的任务来说,它可能过于复杂(因为使用JOptionPane
可以很容易地完成),但它展示了如何使用JDialog
。看起来像ShowDialogActionListener
类。对话框被设置为可见,在对话框关闭之前(即从对话框中获得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");
上述操作也会阻止流执行。
在类之间传递事件的技巧是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();
}
}