java - JList 变为空白 [我认为输出流缓冲问题]

标签 java swing jlist outputstream

我有这个 JList,我将其用作 System.out 的显示。我正在使用 JFrame 底部的这个 JList 创建一个 IRC 客户端。似乎每当 2 个或更多元素同时添加到 JLists ListModel 时,整个 JList 就会变成白色且不可交互,直到有一个元素为止是自己添加的。同时添加多个元素的一个示例是异常打印堆栈跟踪时。

这是我设置为System.outOutputStream类...

public class LogOutputStream extends OutputStream {
    String sentence = "";
    boolean writing = false;
    private DefaultListModel subject;

    public LogOutputStream(DefaultListModel logListModel) {
        this.subject = logListModel;
    }

    public void write(final int b) {
        try {
            sentence = sentence + (char) b;

            if (sentence.endsWith("\n") && !sentence.isEmpty() && !sentence.equals("\t") && !sentence.equals("\r\n") && !sentence.equals("\n")) {
                if (writing == false) {
                    writing = true;
                    subject.addElement(sentence.replaceAll("\n", "").replaceAll("\r", "").trim());
                }

                sentence = "";
                writing = false;
            }
        } 
        catch (Exception e) {
            e.printStackTrace(Boot.stdErr);
        }
    }
}

有谁知道这里发生了什么以及如何解决它?

最佳答案

这可能是 Swing 并发问题,因为您正在将项目添加到事件线程之外的 JList 模型中。这可能会占用线程并阻止它执行绘制 GUI 或允许用户交互有效卡住 Swing GUI 的必要操作。

尝试确保仅在 EDT(Swing 事件调度线程)上写入 JList。像这样的事情会将 Swing 事件线程上的 addElement(...) 调用排队:

public void write(final int b) {
    try {
        sentence = sentence + (char) b;
        if (sentence.endsWith("\n") && !sentence.isEmpty()
                && !sentence.equals("\t") && !sentence.equals("\r\n")
                && !sentence.equals("\n")) {
            if (writing == false) {
                writing = true;
                final String text = sentence.replaceAll("\n", "")
                                .replaceAll("\r", "").trim();
                javax.swing.SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        subject.addElement(text);
                    }
                });

            }
            sentence = "";
            writing = false;
        }
    } catch (Exception e) {
        e.printStackTrace(Boot.stdErr);
    }
}

编辑 1
这更接近于我过去使用 StringBuilder 所做的事情:

import java.io.IOException;
import java.io.OutputStream;

import javax.swing.DefaultListModel;
import javax.swing.SwingUtilities;

public class JListOutputStream extends OutputStream {
   private DefaultListModel logListModel;
   private StringBuilder sb = new StringBuilder();   

   public JListOutputStream(DefaultListModel logListModel) {
      this.logListModel = logListModel;
   }

   @Override
   public void write(int b) throws IOException {
      if (b == '\r')
         return;

      if (b == '\n') {
         final String text = sb.toString().trim();
         sb.setLength(0);
         if (text.isEmpty()) {
            return;
         }
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               logListModel.addElement(text);
            }
         });

         return;
      }

      sb.append((char) b);
   }

}

编辑2
根据这篇题为 Writing Your Own Java I/O Stream Classes 的文章,如果您要扩展 OutputStream,请不要忘记为 flush()close() 方法提供自定义实现。

关于java - JList 变为空白 [我认为输出流缓冲问题],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11181918/

相关文章:

java - gson.toJson() 在 Servlet 中抛出 StackOverflowError

java - 我如何使用一个 Java 程序来监视另一个 Java 程序的输出?

java - Swing:鼠标事件和工具提示

java - 如何限制 JTextArea 中的行数?

java - 在 Android 应用程序中使用线程

java - 使用java反射进行静态代码分析

java - JScrollPane 不能在我的 JTextArea 上工作?

java - 如何在 Java Eclipse 中使用 ArrayList 更改 DefaultListModel

Java jList 根据组合框选择添加项目

java - 如何通过双击来编辑 JList 项目文本?