0

So this is in reference to my previous questions here and here. Basically the problem I am having is the program goes into the Server class and stays there because there is a while look in the server code that essentially is continuously listening to the port for any response from the client; this makes the Main window completely unclickable since the program is not in the MainWindow class.

But really what I want it to do is setup the connection and then go back to MainWindow so the on-screen buttons are clickable. Or, as suggested by one poster, I could pass the MainWindow object by reference to the Server (which I have already done) and then use SwingUtilities.invokeLater() but I'm not really looking to update the GUI. I'm looking to give control back to the GUI so the user can click buttons and such.

When it goes back to MainWindow, I still need the connection to stay alive so the client can send things and I can receive it and display the received content on the screen for the user to control.

Community
  • 1
  • 1
Richard
  • 5,840
  • 36
  • 123
  • 208
  • 3
    And what's wrong with using a [`SwingWorker`](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) for talking with the server? – MadProgrammer Mar 27 '14 at 04:14
  • @MadProgrammer So would I use SwingWorker from the `MainWindow` class so that the connection can be setup separetly? I'm not quite sure how SwingWorker works...even after reading the docs... – Richard Mar 27 '14 at 04:36
  • @MadProgrammer so if I am understanding this correctly, it seems I will setup an object like so: `SwingWorker worker = new SwingWorker...` with the functions that need to be executed inside this worker object. However, the Server is an entire class so how will I encapsulate that into the SwingWorker object? – Richard Mar 27 '14 at 04:46

1 Answers1

2

Basically, you could use a SwingWorker to perform actions in the background, off the Event Dispatching Thread, which will allow you application to continue working...

SwingWorker<Server , Object> worker = new SwingWorker<Server , Object>() {
    @Override
    protected ServerdoInBackground() throws Exception {
        Server server = new Server();
        //...
        // Use publish(...) to send information
        // back the EDT via the process method...
        return server;
    }

    @Override
    protected void done() {
        try {
            Server server = get();
        } catch (InterruptedException | ExecutionException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    protected void process(List<Object> chunks) {
        // You can safly update the UI from here, maybe
        // with some messages??
    }

};
worker.execute();

Basically, this creates a new Server object in the doInBackground method, does what ever else it needs to do that might otherwise block the EDT and exits by returning the server instance.

You can use done if you want to be notified when the doInBackground method completes and either get the result of the method, or if it threw an exception, handle the exeption.

The publish/process methods can be used to send information back to the EDT, which could be used to update the state of the UI...or not...

Now, if you already have a reference to the server, may consider creating a custom SwingWorker to which you pass the reference of the Server to...

Server server = ...;
ConnectionWorker worker = new ConnectionWorker(server);
worker.execute();

//...

public class ConnectionWorker extends SwingWorker<Object, Object> {

    private Server server;
    public ConnectionWorker(Server server) {
        this.server;
    }

    @Override
    protected ServerdoInBackground() throws Exception {
        server.doStuff(); //...
        return ...;
    }

}

Take a look at SwingWorker more details

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366