Imme22009
Imme22009

Reputation: 4129

Passing data from GUI to event dispatch thread in Swing

I am developing a Swing/Java app but having difficulties passing data from the initiliaser threads to one of the GUIs.

The GUI is initialised by invoking an initComponents() method on the event dispatch thread in its run() method:

javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {

            ChatSession ed = new ChatSession(client);

            ed.initComponents();

            ed.setVisible(true);

        }
    });

In ChatSession.java, I have a method initComponents() which contains the line:

conversation = new javax.swing.JTextArea();

I then need to update the GUI from another method in the ChatSession.java object which is listening for TCP packets. I need to append new text that comes in over the TCP socket to the 'conversation' JTextArea on the GUI.

How can I do this? I have tried using invokeLater to run a method on the event dispatch thread, but I get a NullPointerException error...???

java.awt.EventQueue.invokeLater(
    new Runnable() {
        public void run()
        {
            //conversation.append(text);
            ChatSession.this.conversation.append("text to append to chatbox");
        }
    });

I have also tried the commented out line and still get a NPE.

I also need to pass data from the event dispatch thread to the ChatSession object on click of a button (in order to send it over the network to another client).

I have a method in ChatSession.java which is assigned to respond to clicks of the button using an ActionListener initialised on the event dispatch thread:

The method in ChatSession.java:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) 
{                                         
     // add to toSend buffer
    toSend.append(sendtext.getText());
}  

.... is assigned to an ActionListener in initComponents() , part of ChatSession.java, (which is run on the event dispatch thread, see earlier):

jButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton1ActionPerformed(evt);
        }
    });

So how do I pass data from the event dispatch thread to the 'initialiser' object, and then how do I pass data from the initialiser back to the event dispatch?

Upvotes: 1

Views: 2081

Answers (2)

Sbodd
Sbodd

Reputation: 11454

You've got the correct way to push data onto the event dispatch thread already, with the SwingUtilities.invokeLater(). The NPE suggests that you've got something else wrong.

Given that this line:

conversation.append(text)

was producing an NPE, there are three options:

  • conversation is null. Did you initialize conversation in the constructor of ChatSession?
  • something else in your ChatSession that gets called inside append() is null
  • The passed-in text is null and append() does not handle that correctly.

You should be able to look at the exception's stack trace to figure out if it's the first problem (the .append() line will be the last line in the trace). If that's the case, make sure you new up conversation. For the other two, look at the first line in your stack trace and see what's broken there.

There are several possible ways to get data off the EDT onto a background thread; which method you want depends on a number of aspects of the "initialiser" object.

Upvotes: 1

twolfe18
twolfe18

Reputation: 2266

I am not entirely clear on all of your questions, but I think you may be structuring your program oddly and creating problems for yourself. Your ChatSession class should change its own text. If your main program has to catch the packets (rather than the ChatSession), you should have setters for the text field on the ChatSession.

Check out this article on Swing's version of MVC.

Upvotes: 0

Related Questions