Java 不是我的母语,我一直在与这个问题作斗争一段时间。
基本上,我发现直接从 init() 调用方法 switchApplets() 和从 init() 产生的新线程中调用它之间的行为差异。
从新线程内部调用它的结果是新的小程序白屏——直到/除非用户调整大小或最小化他们的浏览器。如果在 init() 结束时调用,新 UI 会立即呈现,无需用户输入任何内容。但这不是一个选项,因为它不会等待线程完成其准备工作。
精简代码:
public class PreLoader extends Applet implements AppletStub {
static JProgressBar pBar = null;
static JLabel message;
public void switchApplets() {
try {
Class main_class = Class.forName("MainClass");
Applet main_applet = (Applet)main_class.newInstance();
removeAll();
setSize(0,0);
setLayout(new GridLayout(1,0));
add(main_applet);
main_applet.init();
main_applet.start();
main_applet.setStub(this);
}
catch (Exception e) {
}
}
public void init() {
pBar = new JProgressBar(0, 100);
pBar.setValue(0);
pBar.setStringPainted(true);
message = new JLabel("Beginning work!");
add(message);
add(pBar);
FlowLayout flow = new FlowLayout();
setLayout(flow);
Thread t = new Thread ( new Runnable () {
public void run ()
{
longRunningFunction1();
longRunningFunction2();
message.setText("Work complete! Stand by..");
switchApplets(); //does NOT work as intended from here
return;
}
} );
t.start();
//switchApplets(); //works as intended if called HERE
}
public void longRunningFunction1() {
//perform some tasks, advance progress bar
}
public void longRunningFunction2() {
//perform some tasks, advance progress bar
}
public void start() {
return;
}
public void appletResize(int width, int height) {
return;
}
}
我尝试让 init() 等待线程完成,以便我可以从那里调用 switchApplets() ,但这只会阻止 EDT 并阻止 UI 更新。还尝试使用 SwingUtilities 的 invokeLater/invokeAndWait,但即使 switchApplets() 在 EDT 上运行,似乎必须直接从 init() 调用它(或至少在线程 init 上运行)才能获得所需的效果.
为什么从新线程中调用 switchApplets() 会导致 UI 行为略有不同(和不需要的)?