Hello StackOverflowers,
我目前正在开发我的第一个客户端/服务器应用程序,并面临一个对我来说根本没有意义的问题。请注意,我是网络编程和使用runnables / threads的新手。
我正在为我的应用程序使用MVC模式,所以我有一个ServerController
,ServerView
和ServerModel
。
现在我的ServerController
中有一个方法,基本上有2个任务。
更新服务器GUI - 应该在JTextArea
中写一个字符串“服务器正在启动...”,以便用户知道应用程序没有崩溃
调用服务器
public ActionListener startServerListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
//Update GUI
view.updateServerNotice(new String("Server is starting..."));
//Start Server in new thread
Thread t1 = new Thread(model);
t1.start();
Thread.sleep(1000);
view.showNotification(model.hostAvailabilityCheck() + "");
} catch (Exception ex)
{
view.showNotification("Server is started already!");
}
}
};
我的问题是,view.updateServerNotice(new String("Server is starting..."));
方法已执行但在服务器未启动之前未显示在GUI中。所以目前它就像点击按钮一样,然后有一点延迟(由于sleep()
)然后,在服务器启动后,GUI会更新为“服务器正在启动......”。
这对我来说没有意义,因为GUI更新肯定是在创建新线程之前执行的。
我希望有人看到我不喜欢的东西,可以帮助我。这不是一个大问题,但我真的很好奇为什么会这样。
提前感谢您的帮助!
答案 0 :(得分:0)
Swing(和AWT,实际上大多数环境中的许多UI框架,而不仅仅是Java)是单线程的:只要您的ActionListener正在运行,就不会绘制任何东西。
你可以做的是在后台线程中运行代码,但在这种情况下,另一个问题就出现了:单线程UI框架并不像其他线程那样随机交互。虽然直接访问有时可能有效,但“合法”方法是使用SwingUtilities.invokeLater或invokeAndWait发送打包到某些Runnable表单中的动作(我在这里使用后者,因此您的消息肯定是可见的):
public ActionListener startServerListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
new Thread(new Runnable({
public void run(){
try{
// Update GUI #1
SwingUtilities.invokeAndWait(new Runnable(){
public void run(){
view.updateServerNotice(new String("Server is starting..."));
}
});
//Start Server in new thread
Thread t1 = new Thread(model);
t1.start();
Thread.sleep(1000);
// Update GUI #2
SwingUtilities.invokeAndWait(new Runnable(){
public void run(){
view.showNotification(model.hostAvailabilityCheck() + "");
}
});
}catch(Exception ex){/*...*/}
}
})).start();
}catch(Exception ex){/*...*/}
}
};
漂亮,不是吗?