Reputation: 5099
I have a JTextPane I'm using to put the chat history of a chat application. There are two sources for it's content right now:
Here's the code used by both methods:
private void appendText(String text, AttributeSet attr) {
try {
int len = history.getDocument().getLength();
history.getDocument().insertString(len, text + "\n", attr);
// Convert the new end location
// to view co-ordinates
Rectangle r = history.modelToView(len);
// Finally, scroll so that the new text is visible
if (r != null) {
scrollRectToVisible(r);
}
} catch (BadLocationException e) {
System.out.println("Failed to append text: " + e);
}
}
Debugging I noticed that the code is executed in both scenarios but only actually shows in the component when is ran in the AWT thread via the GUI.
So unless someone else has a better idea I have the following options:
Any ideas/suggestions?
Upvotes: 1
Views: 1337
Reputation: 44
Try this:
private void appendText(String text, AttributeSet attr) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
// your method code here
}
});
}
It looks like you are trying to update swing components outside the AWT thread since you are calling appendText directly from your client's thread. You can't do that. Now if you use EventQueue.invokeLater, it will make sure the code that updates the swing components gets executed in the AWT thread no matter from which thread you called the method.
Upvotes: 3
Reputation: 76508
I believe you should create a class which holds information about the message (like message text, sender, receiver, timestamp). Like this:
public class ChatHistoryElement {
private String text;
private Date moment;
private User sender;
private User receiver;
public volatile volatile AbstractList<ChatHistoryElement> chatHistory = null;
public String getMessage() {
return text;
}
public Date getMoment() {
return moment;
}
public User getSender() {
return sender;
}
public User getReceiver() {
return receiver;
}
public ChatHistoryElement(String text, Date moment, User sender, User receiver) {
this.text = text;
this.moment = moment;
this.sender = sender;
this.receiver = receiver;
if (chatHistory == null) {
chatHistory = new ArrayList<ChatHistoryElement>();
}
chatHistory.add(this);
}
}
By making your history volatile, you will always be able to reach it using ChatHistoryElement.chatHistory
.
Upvotes: 0