2

JListのディスプレイとして使用しているこれがありますSystem.outJListの一番下にある IRC クライアントを作成していJFrameます。2 つ以上の要素が同時に に追加されると、 1 つの要素が単独で追加されるまでJLists ListModel全体が白くなり、インタラクティブではなくなるようです。JList複数の要素が同時に追加される例としては、例外によってスタック トレースが出力される場合があります。

これが私が持っているOutputStreamクラスで、次のように設定されていSystem.outます...

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

ここで何が起こっているのか、どうすれば修正できるのか誰か知っていますか?

4

1 に答える 1

2

イベント スレッドから離れた JList のモデルに項目を追加しているという点で、Swing の同時実行の問題である可能性があります。これによりスレッドが拘束され、スレッドが GUI の描画に必要なアクションを実行できなくなったり、ユーザーとの対話が事実上 Swing GUI をフリーズしたりする可能性があります。

EDT (Swing Event Dispatch Thread) の JList にのみ書き込むようにしてください。addElement(...)このようなものは、Swing イベント スレッドで呼び出しをキューに入れます。

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独自の Java I/O ストリーム クラスの作成
というタイトルのこの記事に従って、 OutputStream を拡張する場合は、およびメソッドのカスタム実装を提供することを忘れないでください。flush()close()

于 2012-06-25T00:22:30.347 に答える