Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在AWT线程中运行代码_Java_Multithreading_Awt_Jtextpane - Fatal编程技术网

Java 在AWT线程中运行代码

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();

我有一个JTextPane,用来放置聊天应用程序的聊天历史记录。目前,它的内容有两个来源:

  • 侦听服务器消息的客户端线程
  • GUI:添加到消息中的JField和按钮(临时,因为所有内容都来自服务器)
  • 以下是两种方法使用的代码:

    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线程中运行时才会在组件中实际显示

    因此,除非其他人有更好的想法,否则我有以下选择:

  • 以某种方式在AWT上运行客户机线程
  • 以某种方式在AWT上运行append方法
  • 用你们中的一个聪明的回答

  • 有什么想法/建议吗?

    我认为您应该创建一个类来保存有关消息的信息(如消息文本、发送者、接收者、时间戳)。像这样:

    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。所以,事实上,我相信这与这个问题有很大关系。