Domanda

Ho un paio di migliaia di linee di codice da qualche parte e ho notato che il mio JTextPane sfarfalla quando aggiorno troppo .. Ho scritto una versione semplificata qui:

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

    }
}

Questo è per un componente terminale (cmd) stile GUI -

Credo di aver fatto tutte le ottimizzazioni che ho potuto qui, compreso avere \n come variabile finale in modo che non sarà costruito centinaia di volte. Ancora, lo sfarfallio è notevole e inaccettabile. Dopo pochi minuti, il componente si blocca completamente. Devo aggiornare il componente molto rapidamente, e il riquadro devo far scorrere verso il basso dopo l'aggiornamento.

Ho pensato di fare la mia versione di JTextPane da zero, ma mi piacerebbe vedere se voi ragazzi avete una soluzione più facile.

È stato utile?

Soluzione

Parte del tuo errore è che si accede a un componente Swing da fuori discussione evento! Sì, setText ( ) è thread-safe, ma i metodi dell'oscillazione non sono thread-safe meno che non siano esplicitamente dichiarate come tali. Così, setCaretPosition () non è thread-safe e deve essere accessibile dal thread evento. Questo è quasi certamente il motivo per cui l'applicazione alla fine si blocca.

NOTA: JTextPane eredita il suo metodo setText() dalla JEditorPane e il suo metodo dal setCaretPosition JTextComponent, che spiega i collegamenti nel paragrafo precedente, non andare al setCaretPosition() JavaDoc.

Per essere thread-safe, si ha realmente bisogno di almeno chiamare <=> dall'interno del filo evento, che si può fare con codice come questo:

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

E dal momento che si deve chiamare <=> dall'interno thread evento, si potrebbe anche chiamare anche <=> dallo stesso posto.

E 'possibile che non si può essere necessario impostare manualmente la posizione del cursore. Controlla la sezione "Caret Changes" nel JavaDoc per JTextComponent .

Infine, si consiglia di controllare una serie di due articoli:

Altri suggerimenti

Non sono sicuro se questo funzionerà, ma si potrebbe provare a utilizzare il metodo della insertString() esempio del riquadro di testo Document. Proverei avente un singolo spazio alla fine del documento e mantenendo il cursore posizionato dopo che lo spazio; ma quando si inserisce una stringa, inserirla prima dello spazio. In questo modo la posizione del cursore rimarrà alla fine del documento automaticamente.

Sto pensando che il riquadro di testo potrebbe essere sempre ridisegnato due volte, una volta che quando si chiama setText() e una volta quando si chiama setCaretPosition(), e che potrebbero contribuire al sfarfallio. Non è sicuro, anche se (è stato un po 'da quando ho lavorato con Swing).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top