2

在我的客户端/服务器 Java 应用程序中,我发现了一个奇怪的行为,它阻止任何内容显示在 JFrame 中,而不是第一个(登录)。

JFrame 已显示,但它是透明的,如果我调整它的大小,我会有这样的效果:

在此处输入图像描述

该应用程序的工作方式是这样的(2个主要的,1个在服务器类中,1个在客户端类中:

SERVER SIDE 1) main 有一个无限循环,当客户端连接到它时启动一个新线程来处理消息

CLIENT SIDE 1) main 获取 GuiLogin JDialog 的单例,并执行一个方法显示它

2) 当用户按下 Login 时,guilogin 中的 ActionListener 调用客户端方法将 LoginRequest 对象分派给 Server,Server 以 LoginResponse 对象进行回复

3)如果电子邮件和密码正确(电子邮件=a,密码=b),它应该显示另一个JFrame,但无论我尝试什么,它总是显示错误 - 透明框架

3b)如果电子邮件和密码不正确,应用程序会显示一个 JDialog(工作正常)

我认为我的错误是概念性的,代码看起来不错,我调用新的 JFrame

   guiLogin.dispose();

   JFrame j = new JFrame();
   j.setVisible(true);

作为独立代码,它可以工作,但是在客户端上我的访客模式消息处理程序中的一个方法中,它的工作原理就像在屏幕截图中一样

eclipse项目的缩小版,剥离了所有与bug无关的类和方法

编辑:我对 Java Gui 和事件非常缺乏经验,我现在检查导致问题的代码在 EDT 内( javax.swing.SwingUtilities.isEventDispatchThread() 返回 true )。我应该在 SwingWorker 线程中移动整个消息处理逻辑吗?

4

1 回答 1

4

你挡住了Event Dispatch Thread (EDT)。这是在 EDT 上执行的片段TinyClient

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 没有重新绘制。

查看Swing 中的并发以获取更多详细信息。您可能希望采用多线程解决方案来处理网络。SwingWorker在同一个教程中查看。它允许在后台线程上执行任务并在 EDT 线程上传达结果。

编辑

由于您的应用程序的详细信息和规模不可用,因此很难给出具体的解决方案。请记住,Swing 是单线程的。所有 UI 工作都必须在 EDT 上完成。为了获得最佳性能,EDT 上的所有任务都应该简短。网络应该在工作线程上处理。您有几个选项,例如SwingWorkerExecutorService或您自己的辅助线程。SwingWorker具有在 EDT 上推送更新的内置机制。如果ExecutorService您可以SwingUtilities.invokeLater用于此目的。

于 2012-09-08T20:18:46.780 回答