简体   繁体   English

JFrame显示不正确

[英]JFrame is not displayed correctly

In my Client/Server Java application, I found out a strange behaviour, that prevents any content to be displayed in a JFrame than the first one (login one). 在我的客户机/服务器Java应用程序中,我发现了一个奇怪的行为,该行为阻止了JFrame中第一个(登录一个)内容以外的任何内容显示在JFrame中。

The JFrame is diplayed, but it's transparent and if I resize it, I have this effect: JFrame已显示,但它是透明的,如果我调整它的大小,则会产生以下效果:

在此处输入图片说明

The application works like this (2 main, 1 in Server class and 1 in Client class: 该应用程序的工作方式如下(2个主类,Server类中的1个,Client类中的1个:

SERVER SIDE 1) the main has an infinite loop, starting a new thread to handle messages when a client connects to it 服务器端1)主服务器具有无限循环,当客户端连接到它时启动一个新线程来处理消息

CLIENT SIDE 1) the main get the singleton of the GuiLogin JDialog, and execute a method to display it 客户端1)主要获取GuiLogin JDialog的单例,并执行显示方法

2) when the user press Login, an ActionListener in the guilogin, invokes the client method to dispatch a LoginRequest object to the Server, that replies with a LoginResponse object 2)当用户按下Login时,guilogin中的ActionListener调用客户端方法以将LoginRequest对象分配给Server,该对象用LoginResponse对象进行回复

3) if the email and password are correct (email=a,password=b), it should display another JFrame, but whatever i tried, it always displayed the bugged - transparent frame 3)如果电子邮件和密码正确(email = a,password = b),它应该显示另一个JFrame,但是无论我尝试什么,它总是显示错误的-透明框架

3b) if the email and password are incorrect, the application displays a JDialog (working fine) 3b)如果电子邮件和密码不正确,应用程序将显示一个JDialog(工作正常)

I think my mistake is somewhere conceptual, the code looks right fine, I invoke the new JFrame with 我认为我的错误是在概念上出现的,代码看起来不错,我使用

   guiLogin.dispose();

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

as standalone code it works, but inside a method in my Visitor-pattern message handler on the client, it works like in the screenshot 作为独立代码,它可以工作,但是在客户端上我的“访客”模式消息处理程序中的方法中,它的工作原理类似于屏幕截图

minified version of the eclipse project, stripped all the class and methods not concerning the bug eclipse项目的缩小版,剥离了所有与错误无关的类和方法

EDIT: I am very inexperienced about Java Gui & events, i checked now that the code causing the issue is inside an EDT ( javax.swing.SwingUtilities.isEventDispatchThread() returns true ). 编辑:我对Java Gui和事件非常缺乏经验,我现在检查了导致问题的代码在EDT内部(javax.swing.SwingUtilities.isEventDispatchThread()返回true)。 Should i move the whole message handling logic inside a SwingWorker thread? 我应该在SwingWorker线程中移动整个消息处理逻辑吗?

You're blocking Event Dispatch Thread (EDT) . 您正在阻止Event Dispatch Thread (EDT) Here is a snippet from TinyClient that is executed on 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);

On one of the iterations in.readObject(); in.readObject();中的一次迭代中in.readObject(); call is blocked. 通话被阻止。 Same goes for the Thread.Sleep . Thread.Sleep All UI related work, such as painting, happen on the EDT. 所有与UI相关的工作(例如绘画)都在EDT上进行。 Once EDT is blocked it does not process any events. 一旦EDT被阻止,它就不会处理任何事件。 Hence the result you see - the UI is not repainted. 因此,您看到的结果是-UI不会重新绘制。

Take a look at Concurrency in Swing for more details. 有关更多详细信息,请参阅Swing中的并发 You would want to adopt a multithreaded solution to handle networking. 您可能希望采用多线程解决方案来处理网络。 Look into SwingWorker in the same tutorial. 在同一教程中研究SwingWorker It allows execution of a task on a background thread and communicate results on EDT thread. 它允许在后台线程上执行任务,并在EDT线程上传达结果。

EDIT : 编辑

As the details and scale of your application are not available it is hard to give a concrete solution. 由于无法提供应用程序的详细信息和规模,因此很难给出具体的解决方案。 Keep in mind that Swing is single threaded. 请记住,Swing是单线程的。 All UI work must be done on EDT. 所有UI工作必须在EDT上完成。 For best performance, all tasks on EDT should be brief. 为了获得最佳性能,EDT上的所有任务应简短。 Networking should be handled on a worker thread. 网络应在辅助线程上处理。 You have several options such as SwingWorker , ExecutorService or your own auxiliary threads. 您有几个选项,例如SwingWorkerExecutorService或您自己的辅助线程。 SwingWorker has a built-in mechanism to push updates on EDT. SwingWorker具有内置机制来推送EDT上的更新。 In case of ExecutorService you can use SwingUtilities.invokeLater for that purpose. 如果使用ExecutorService ,则可以为此使用SwingUtilities.invokeLater

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM