Java CardLayout .show() not showing
我在像while循环这样的"阻塞"代码之前使用
这是显示问题的代码:
(警告:此代码包含while true循环。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import javax.swing.JFrame; import java.awt.CardLayout; import java.awt.event.ActionEvent; import javax.swing.JPanel; import javax.swing.JLabel; import javax.swing.JButton; public class CardTest extends JFrame{ public CardTest() { CardLayout cl = new CardLayout(0,0); getContentPane().setLayout(cl); JPanel panelA = new JPanel(); getContentPane().add(panelA,"PanelA"); JLabel lblPanelA = new JLabel("Panel A"); panelA.add(lblPanelA); JButton btnSwitchToPanel = new JButton("Switch to Panel B"); panelA.add(btnSwitchToPanel); JPanel panelB = new JPanel(); getContentPane().add(panelB,"PanelB"); JLabel lblPanelB = new JLabel("Panel B"); panelB.add(lblPanelB); btnSwitchToPanel.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent event) { cl.show(getContentPane(),"PanelB"); getContentPane().revalidate(); // Here is the problem. Even though cl.show is called first, // it still doesn't show, before the while loop has terminated. int i = 0; while(i < 1000000){ i++; System.out.println(i); } } }); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setVisible(true); } public static void main(String[] args){ new CardTest(); } } |
如果您想知道,我需要一个下载器,在第一个面板中按一个按钮后,会调用while true循环(下载文件)。 第二个面板包含进度条。 但是,即使在下载代码之前调用了.show函数,也不会显示进度面板。
更新
我确实知道将循环放到新线程中可以解决绘制问题,但同时也带来了其他问题,因为我依赖循环(下载文件(循环),解压缩文件,移动这些文件)之后的顺序执行功能。 )。
最好的解决方案是找到一种方法,允许.show()调用在继续循环之前实际花费时间切换窗格。
I use .show() before a"blocking" code like a while loop. But even though the .show gets called, the UI doesn't actually show the called panel.
是的,因为您正在"阻止"负责重新绘制GUI的事件调度线程(EDT)。因此,在代码完成执行之前,GUI无法重绘自身。
您需要创建一个单独的线程来执行长时间运行的任务,以免阻塞EDT。一种方法是使用
阅读Swing并发教程中的这一节,以获取更多信息和工作示例。
这是因为重新绘制UI是在与事件处理相同的线程中完成的,并且直到事件处理完成(即,所有事件处理方法都已返回)之后才会发生。
最好的办法是将"阻塞"代码移入可运行代码,并在工作线程中执行它。
发生这种情况的原因是您正在EventDispatchingThread上进行工作。该线程还负责实际绘制GUI。
除了在另一个线程中进行工作之外,您别无选择。
例如:(快速+肮脏)
1 2 3 4 5 6 |