在我的客户端/服务器Java应用程序中,我发现了一个奇怪的行为,它阻止任何内容显示在JFrame中而不是第一个(登录一个)。
JFrame是diplayed,但它是透明的,如果我调整它,我有这个效果:
应用程序的工作原理如下(2个主要,1个在Server类中,1个在Client类中:
服务器端 1)main有一个无限循环,启动一个新线程来处理客户端连接它时的消息
客户端 1)main获取GuiLogin JDialog的单例,并执行一个方法来显示它
2)当用户按下Login时,guilogin中的ActionListener调用客户端方法将LoginRequest对象分派给Server,该对象使用LoginResponse对象进行回复
3)如果电子邮件和密码是正确的(email = a,password = b),它应该显示另一个JFrame,但无论我尝试什么,它总是显示错误的透明框架
3b)如果电子邮件和密码不正确,应用程序将显示JDialog(正常工作)
我认为我的错误是概念性的,代码看起来很好,我用
调用新的JFrame guiLogin.dispose();
JFrame j = new JFrame();
j.setVisible(true);
作为它的独立代码,但在客户端的访问者模式消息处理程序中的方法内,它的工作方式与截图相同
minified version of the eclipse project, stripped all the class and methods not concerning the bug
编辑:我对Java Gui& amp;事件,我现在检查导致问题的代码是在EDT内(javax.swing.SwingUtilities.isEventDispatchThread()返回true)。我应该在SwingWorker线程中移动整个消息处理逻辑吗?答案 0 :(得分:4)
您正在屏蔽Event Dispatch Thread (EDT)
。以下是来自TinyClient
的片段,该片段在EDT上执行:
do {
System.out.println("waiting response");
try {
Response risp = (Response) in.readObject();
risp.accept(resHandler);
}
catch (SocketException e) {
// unhandled yet
}
Thread.sleep(500);
} while (waitForMessage);
在其中一个迭代in.readObject();
上,呼叫被阻止。同样适用于Thread.Sleep
。所有与UI相关的工作,例如绘画,都发生在EDT上。一旦EDT被阻止,它就不会处理任何事件。因此,您看到的结果 - UI不会重新绘制。
查看Concurrency in Swing了解更多详情。您可能希望采用多线程解决方案来处理网络。在同一个教程中查看SwingWorker
。它允许在后台线程上执行任务并在EDT线程上传递结果。
编辑 :
由于您的申请的详细信息和规模不可用,因此很难给出具体的解决方案。请记住,Swing是单线程的。所有UI工作必须在EDT上完成。为了获得最佳性能,EDT上的所有任务都应该是简短的。网络应该在工作线程上处理。您有几个选项,例如SwingWorker
,ExecutorService
或您自己的辅助线程。 SwingWorker
有一个内置机制来推送EDT上的更新。如果是ExecutorService
,您可以将SwingUtilities.invokeLater
用于此目的。