質問

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).

The JFrame is diplayed, but it's transparent and if I resize it, I have this effect:

enter image description here

The application works like this (2 main, 1 in Server class and 1 in Client class:

SERVER SIDE 1) the main has an infinite loop, starting a new thread to handle messages when a client connects to it

CLIENT SIDE 1) the main get the singleton of the GuiLogin JDialog, and execute a method to display it

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

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

3b) if the email and password are incorrect, the application displays a JDialog (working fine)

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

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 ). Should i move the whole message handling logic inside a SwingWorker thread?

役に立ちましたか?

解決

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

On one of the iterations in.readObject(); call is blocked. Same goes for the Thread.Sleep. All UI related work, such as painting, happen on the EDT. Once EDT is blocked it does not process any events. Hence the result you see - the UI is not repainted.

Take a look at Concurrency in Swing for more details. You would want to adopt a multithreaded solution to handle networking. Look into SwingWorker in the same tutorial. It allows execution of a task on a background thread and communicate results on EDT thread.

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. All UI work must be done on EDT. For best performance, all tasks on EDT should be brief. Networking should be handled on a worker thread. You have several options such as SwingWorker, ExecutorService or your own auxiliary threads. SwingWorker has a built-in mechanism to push updates on EDT. In case of ExecutorService you can use SwingUtilities.invokeLater for that purpose.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top