In my main application class I have an object of JTextArea(say txtArea). I have created two another threads in main_application program. The two threads I have created is for reading and writing in serial port. Now I want to put the serial port read buffer data into an JTextArea object. So I need to pass the JTextArea object created in main_application to read-thread so that read-thread can put the read output to JTextArea.开发者_StackOverflow中文版
But after doing like this I am facing null pointer access problem. When I check the JTextArea object in main_application its not null but after passing to thread i checked its null. I dont know how it happens.... if any geek can help me i will be happy....
Thanks , Surjya
As mentioned in another response, you can only change the contents of a Swing component on the swing thread itself. A good way to ensure that all your other threads do this is to not expose the actual JTextArea, but rather to provide the other objects with a safe method to add text to the text area from your main_application, like so:
public class main_application {
private JTextArea txtArea;
public void addText(final String txt) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
txtArea.setText(txtArea.getText() + txt);
}
});
}
}
This is a simple example, but you can expand on this based on your needs. This also uses a more costly way of adding to the text since it appends two immutable strings. You could use JTextArea.getDocument() to retrieve the model and then use the mutation methods in the document to more efficiently update the text. However, by providing a method like this you can change the implementation in the future without affecting your other threads or objects.
Note that the parameter txt is final which is required so that it can be directly referenced in the anonymous inner class.
You may want to decouple this from your main application class and create an interface or class for the method(s)/way(s) you want to manipulate the text area from your other threads and then hand them an object that wraps this text area.
Sharing objects between threads can get very messy, you may want to read about the Actor model for a different approach. Specifically in the GUI arena, an Model-View-Controller approach code help out.
But back the the question, you could quickly hack it by making your JTextArea a static variable and just letting all the different threads modify the static instance at will:
public static JTextArea TXTAREA
void main_application(){
//set up app
...
TXTAREA = new JTextArea()
...
}
then in your serial reading thread, set the text for TXTAREA
. This solution is not ideal, I think a better approach would be to use an MVC approach and have a controller which accepts the value to put in the text area.
Take a look at SynchronousQueue:
http://java.sun.com/javase/6/docs/api/java/util/concurrent/SynchronousQueue.html
It will allow you to store an object into the queue and will then wait until it is removed.
- Publishing JTextArea reference to another thread is not correct because Swing compoments are MVC-based (model-ui actually). So, your general way to work with swing components is to update their models and let view (ui) display the change;
- Another point is that most of swing componenets aren't thread-safe, i.e. you can't be sure that your application works fine if you use swing component from the thread over than EDT;
So, you should do the following: every time you have new data to display submit new task of JTextArea content update to be executed from the EDT. You can achieve that via SwingUtilities.invokeLater()
精彩评论