![](/img/trans.png)
[英]ActionListener executes twice on JPanel when called from JFrame
[英]JFrame not showing up properly when called from ActionListener
public class Start extends JFrame{
public static void main(String...s){
Start obj = new Start();
obj.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
obj.setBounds(100,100,300,300);
JPanel main = new JPanel();
obj.add(main);
JButton btn = new JButton("Login");
main.add(btn);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
obj.setVisible(false);
obj.dispose();
new Progress();
}
});
obj.setVisible(true);
}
}
class Progress extends JFrame{
int pro = 0;
Progress(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBounds(100,100,300,300);
JPanel main = new JPanel();
add(main);
main.add(new JLabel("ejfbasj"));
JProgressBar progressBar = new JProgressBar(0,100);
main.add(progressBar);
Thread t1 = new Thread() {
public void run() {
while(pro<=100) {
/*
* Do something - set progressbar value
* */
try {
sleep(10);
} catch (InterruptedException e) {}
progressBar.setValue(pro);
pro++;
}
}
};
t1.start();
//Do something - gives progress values
try {
t1.join();
} catch (InterruptedException e) {}
}
}
以上是我的问题的最小的、可重现的例子。
从 ActionListner 调用 Progress JFrame 时,JFrame 未正确显示。 我得到一个黑色的 JFrame,一秒钟后我得到了带有完整进度条的最终 JFrame。 但是如果我直接调用new Progress()
,它会正常工作(即看到进度条填满)。
我发现在UI线程中新建Thread是无法绘制Frame的。 我应该使用Swing.Timer
。
我不知道如何使用Swing.Timer
来做到这一点。 任何其他方法表示赞赏。
obj.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
有直接的问题,但还有更多。 将其更改为以下内容以确保 JRE 在处理后不会退出:
obj.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
至于其他一些问题:
CardLayout
在一个框架中显示两个面板。JDialog
而不是第二帧。Throwable.printStackTrace()
Progress(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
在建立 UI 之后,最后调用setVisible
。 如果您需要在 UI 可见后更新它,您应该调用invalidate
和repaint
来触发新的布局和绘制通道
Thread t1 = new Thread() {
public void run() {
while(pro<=100) {
/*
* Do something - set progressbar value
* */
try {
sleep(10);
} catch (InterruptedException e) {}
progressBar.setValue(pro);
pro++;
}
}
};
t1.start();
//Do something - gives progress values
try {
t1.join();
} catch (InterruptedException e) {}
好的,这实际上是两个问题。
首先,Swing 不是线程安全的,您不应该从事件调度线程的上下文之外更新 UI。 正如您所说,您应该使用 Swing Timer
或者可能更合适地使用SwingWorker
其次, t1.join
阻塞了当前线程。 因为此构造函数是从ActionListener
调用的,这意味着您处于事件调度线程的上下文中,即用于更新 UI 的线程,因此,在线程完成之前不会发生任何变化
例如:
我还将讨论有关使用多个框架、 setBounds
之类的东西pack
、 setLocationRelativeTo
以及使用其他东西(例如边框或布局约束)来增加填充的事情,但是还有很多其他示例
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.