Frage

Ich habe ein paar tausend Zeilen Code irgendwo, und ich habe bemerkt, dass mein JTextPane flackert, wenn ich es zu viel aktualisieren .. ich eine vereinfachte Version schrieb hier:

import java.awt.*;
import javax.swing.*;

public class Test
{
    static JFrame f;
    static JTextPane a;
    static final String NL = "\n";

    public static void main(String... args)
    {
        EventQueue.invokeLater(new Runnable(){
        public void run()
        {
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.setSize(400, 300);
        f.setLocationRelativeTo(null);

        a = new JTextPane();
        f.add(new JScrollPane(a));

        new Thread(new Runnable(){
            public void run()
            {
                int i = 0;
                StringBuffer b = new StringBuffer();
                while(true)
                {
                    b.append(++i+NL);
                    a.setText(b.toString());
                    a.setCaretPosition(b.length());
                    try{Thread.sleep(10);}catch(Exception e){}
                }
            }
        }).start();
        }
        });

    }
}

Dies ist für einen Terminal (cmd) Stil GUI-Komponente -

Ich glaube, ich habe alle Optimierungen vorgenommen ich hier kann, einschließlich \n als letzten Variable ist, so wird es nicht hunderte Male aufgebaut werden. Dennoch ist das Flackern bemerkbar und nicht akzeptabel. vollständig nach einigen Minuten friert das Bauteil. Ich muß die Komponente sehr schnell aktualisieren, und die Scheibe muss nach unten gescrollt werden, wenn aktualisiert.

Ich habe darüber nachgedacht, meine eigene Version von JTextPane von Grund auf neu zu machen, aber ich würde gerne sehen, wenn euch eine einfachere Lösung.

War es hilfreich?

Lösung

Ein Teil Ihrer Fehler ist, dass Sie eine Swing-Komponente von außerhalb des Ereignis-Thread zugreifen! Ja, setText ( ) ist Thread-sicher, aber Swing-Methoden Thread-sicher sind, sofern sie nicht ausdrücklich als solche deklariert werden. So setCaretPosition () ist nicht Thread-sicher und muss aus dem Event Thread zugegriffen werden. Dies ist fast sicher, warum Ihre Anwendung schließlich gefriert.

Hinweis: JTextPane erbt seine setText() Methode von JEditorPane und seine setCaretPosition Methode von JTextComponent, die die Verbindungen im vorherigen Absatz erklärt nicht gehen in die JTextPane JavaDoc Seite.

Thread-sicher sein, Sie müssen wirklich zumindest Anruf setCaretPosition() aus dem Event Thread, die Sie mit Code wie folgt tun:

SwingUtilities.invokeAndWait(new Runnable() {
  public void run() {
    a.setText(b.toString());
    a.setCaretPosition(b.length());
  }
}

Und da Sie setCaretPosition() aus dem Event Thread nennen haben, könnte man genauso gut auch setText() von der gleichen Stelle nennen.

Es ist möglich, dass Sie nicht manuell die Position der Einfügemarke eingestellt müssen möglicherweise. Schauen Sie sich den Abschnitt "Caret Changes" in der JavaDoc JTextComponent .

Schließlich können Sie eine Serie von zwei Artikeln überprüfen:

Andere Tipps

Nicht sicher, ob dies funktionieren wird, aber man könnte versuchen, die insertString() Methode des Textbereiches des Document Instanz verwenden. Ich würde versuchen, einen einzigen Raum am Ende des Dokuments mit und den Cursor nach diesem Raum positioniert zu halten; aber wenn Sie eine Zeichenfolge einfügen, legen Sie sie vor dem Raum. Auf diese Weise die Position der Einfügemarke automatisch am Ende des Dokuments bleiben wird.

Ich denke, dass der Textbereich zweimal neu gezeichnet werden könnte bekommen, einmal, wenn Sie setText() ruft und einmal, wenn Sie setCaretPosition() nennen, und dass zum Flimmern beitragen könnte. Nicht sicher, aber (es ist schon eine Weile her, seit ich mit Schaukel gearbeitet).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top