我需要一个简单的java应用程序的帮助,该应用程序使用两个jframe来获取一些输入参数。这是我的代码草图:
//second jframe, called when the button OK of the first frame is clicked
public class NewParamJFrame extends JFrame{
...
}
//first jframe
public class StartingJFrame extends JFrame{
private static NewParamJFrame newPFrame = null;
private JTextField gnFilePath;
private JButton btnOK;
public StartingJFrame(){
//..
initComponents();
}
private void initComponents(){
btnOK.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
EventQueue.invokeAndWait(new Runnable(){
public void run() {
try {
newPFrame = new NewParamJFrame();
newPFrame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
catch(InvocationTargetException e2) {}
catch(InterruptedException e1){}
dispose();
}
}
public String getText(){
return gnFilePath.getText();
}
}
public class Main {
private static StartingJFrame begin = null;
public static void main(String[] args) {
try{
EventQueue.invokeAndWait(new Runnable(){
public void run() {
try {
begin = new StartingJFrame();
begin.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
catch(InvocationTargetException e) {}
catch(InterruptedException e1){}
String s= begin.getText();
//...use s ...
}
}
对getText()的调用会导致NullPointerException。我希望主类等到框架关闭,但我不知道该怎么做。我是第一次使用swing。
我希望主类等到框架关闭,但我没有知道怎么做。我是第一次用秋千。
如果我正确理解您的问题,那么您需要StartingJFrame
等待NewParamJFrame
关闭,然后继续执行。如果是这种情况,那么它就不会发生,因为JFrame
不支持模态。但是JDialog
有,所以您可以只有一个JFrame
,并在父级为JFrame
的JDialog
中进行参数请求。
要更好地解释情态,请阅读"如何在对话框中使用情态"。
还可以看看这个主题:多个JFrame的使用,好的/坏的实践?
无论如何,您可能会面临一个新问题:如果用户在没有输入任何参数的情况下关闭/取消对话框,JFrame
应该怎么办?这个JFrame
怎么会知道刚才在对话中发生了什么?在这个答案中描述了一种方法。你会看到这个例子是关于登录对话框的,但问题与这个类似:对话框如何通知其父框架进程的进展?
在不修改代码流的情况下等待关闭的最简单方法是使用模式JDialog
。因此,您必须更改StartingJFrame
类,使其成为JDialog
的子类,而不是JFrame
,并在其构造函数的开头添加以下内容:
super((Window)null);
setModal(true);
然后StartingJFrame
实例上的setVisible(true);
调用将等待,直到对话框关闭,因此invokeAndWait
调用也将等待。
对getText()的调用会导致NullPointerException。
因为,JTextField
的gnFilePath
就是null
。
private JTextField gnFilePath;
public String getText(){
return gnFilePath.getText();// NullPointerException is throw here.
}
为了避免NPE
,您需要初始化JTextField
和JButton
,如下所示。
private JTextField gnFilePath=new JTextField();
private JButton btnOK=new JButton()
试着放这个:
import java.awt.event.*;
import javax.swing.*;
public class MyWindow extends JFrame{
MyWindow(){
setSize(300, 200);
setLayout(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton b = new JButton("Close");
b.setBounds((300-80)/2, (200-30)/2, 80, 30);
//
final MyWindow frame = this;
b.addActionListener(
new ActionListener(){
@Override
public void actionPerformed(ActionEvent ev){
synchronized(frame){
frame.notify();
}
frame.setVisible(false);
frame.dispose();
}
}
);
//
getContentPane().add(b);
setVisible(true);
synchronized(this){
try{
this.wait();
}
catch(InterruptedException ex){ }
}
}
public static void main(String args[]) {
new MyWindow();
System.out.println("You are here");
}
}
已检查上面的代码。
使用JDialog可能是最简单的解决方案,但在某些情况下,最好有一个JFrame,例如在任务栏中显示窗口。使用Octavio建议的同步机制是实现这一点的一种方法,这里有一种使用CountDownLatch阻塞主线程直到帧关闭的替代方法:
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setSize(300, 200);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
latch.countDown();
}
});
});
latch.await();
System.out.println("Main thread released");
}
您可以使用循环(最好是do-while循环)来保持一个帧,直到另一个帧关闭或隐藏。当其他帧被释放或隐藏时,请确保打断循环或将用于循环的变量增加特定的量。通过这种方式,您可以将StartingJFrame
类保留为JFrame
的子类。
do {
if (changeLog.isVisible()) {
} else {
changeLog.dispose();
break;
}
} while (hold < 1);
或
do {
if (changeLog.isActive()) {
} else {
break;
}
} while (hold < 1);
第一个将要求在运行代码之前隐藏前一帧(JFrame.HIDE_ON_EXIT
或Window.setVisible(false)
)。最后一个需要"丢弃"前一帧(JFrame.DISPOSE_ON_EXIT
或(subclass of JFrame).dispose()
)。不过,在StartingJFrame
上添加任何这些代码,因为您在该类中创建了NewParamJFrame
,并将相应的字段设置为private
。