tags:

views:

606

answers:

2

Hi,

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 Action Listener 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?

A: 

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.

twolfe18
thanks for the tip on getters and setters. I have restructured my code to use that. And the tip on structuring. very helpful
Imme22009
+1  A: 

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.

Sbodd
many thanks for the great answer. conversation was indeed null. the problem was that I wasn't creating it on the dispatch thread. The solution that works was to replace the 'ed' object I created with a blank object and create 'conversation' like eg. initComponents() in run() rather than ed.initComponents()
Imme22009