Java 在AWT线程中运行代码
我有一个JTextPane,用来放置聊天应用程序的聊天历史记录。目前,它的内容有两个来源:Java 在AWT线程中运行代码,java,multithreading,awt,jtextpane,Java,Multithreading,Awt,Jtextpane,我有一个JTextPane,用来放置聊天应用程序的聊天历史记录。目前,它的内容有两个来源: 侦听服务器消息的客户端线程 GUI:添加到消息中的JField和按钮(临时,因为所有内容都来自服务器) 以下是两种方法使用的代码: private void appendText(String text, AttributeSet attr) { try { int len = history.getDocument().getLength();
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);
}
}
调试时,我注意到代码在两种情况下都会执行,但只有在通过GUI在AWT线程中运行时才会在组件中实际显示
因此,除非其他人有更好的想法,否则我有以下选择:
有什么想法/建议吗?我认为您应该创建一个类来保存有关消息的信息(如消息文本、发送者、接收者、时间戳)。像这样:
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);
}
}
公共类ChatHistoryElement{
私有字符串文本;
私人约会时刻;
私人用户发送者;
私人用户接收器;
public volatile AbstractList chatHistory=null;
公共字符串getMessage(){
返回文本;
}
公开日期{
返回力矩;
}
公共用户getSender(){
发信人;
}
公共用户getReceiver(){
返回接收器;
}
public ChatHistoryElement(字符串文本、日期时刻、用户发送者、用户接收者){
this.text=文本;
这个时刻=时刻;
this.sender=发送方;
this.receiver=接收器;
if(chatHistory==null){
chatHistory=新的ArrayList();
}
添加(这个);
}
}
通过使您的历史记录不稳定,您将始终能够使用ChatHistoryElement访问它。chatHistory
private void appendText(String text, AttributeSet attr) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
// your method code here
}
});
}
看起来您正试图在AWT线程之外更新swing组件,因为您直接从客户端线程调用appendText。你不能那样做。现在,如果您使用EventQueue.invokeLater,它将确保更新swing组件的代码在AWT线程中执行,无论您从哪个线程调用该方法。这是我在发布之前就测试过的,不起作用。在方法和客户端线程中尝试了这一点,得到了相同的结果。这是正确的答案,我的问题与此无关。最后,这确实解决了问题背后的问题。不确定这与问题有什么关系。存储此列表超出了将其显示在TextPane上的目的。您也可以将TextPane定义为volatile。问题是,任何线程都可以访问易失性成员。我喜欢将UI内容保存在UI线程中,因此我认为只共享重要的内容是更好的,UI线程应该根据列表定期刷新TextPane。所以,事实上,我相信这与这个问题有很大关系。