JScrollPane e JList scorrimento automatico
-
22-09-2019 - |
Domanda
Ho il codice successivo:
listModel = new DefaultListModel();
listModel.addElement(dateFormat.format(new Date()) + ": Msg1");
messageList = new JList(listModel);
messageList.setLayoutOrientation(JList.VERTICAL);
messageScrollList = new JScrollPane(messageList);
messageScrollList.setPreferredSize(new Dimension(500, 200));
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
}
});
Si scorre auto verso il basso. Ma, se provo a scorrere indietro fino a ri-leggere un messaggio, costringe uno scorrimento verso il basso. Come posso risolvere questo problema?
Soluzione
Quando si aggiunge un nuovo messaggio, richiamare scrollRectToVisible()
sulla JList
utilizzando un Rectangle
vista le stesse dimensioni dimensione preferita del riquadro dei messaggi. Dato un orientamento verticale, può essere conveniente per rendere la dimensione preferita del JScrollPane
's JViewport
un multiplo intero della altezza del riquadro dei messaggi. Vedi anche: Come usare Scroll Panes .
Addendum: Questo interessante discussione di Testo Area di scorrimento può essere utile, anche.
Altri suggerimenti
Ho trovato questo veramente utile:
http://forums.sun.com/thread.jspa?threadID=623669 (messaggio di 'inopia')
Funziona perfettamente
Come egli dice: "Il problema qui è che può diventare un po 'difficile trovare un evento che spara dopo sia il ListModel, JList e JScrollPane sono stati aggiornati."
this.list = blah blah...
this.list.setSelectedValue(whatever);
final JScrollPane sp = new JScrollPane(this.list); // needs to be after the parent is the sp
this.list.ensureIndexIsVisible(this.list.getSelectedIndex());
@question Enquirer. Si prega di modificare il codice da
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
}
});
a
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getValue());
}
});
Questo è il cambiamento getMaximum()
per getValue()
allora funziona come richiesto. getMaximum()
prende lo scroller al massimo; mentre getValue()
prende ovunque evento si verifica.
È possibile evitare l'uso di questo pezzo di codice del tutto, se si mette una riga
messageScrollList.setViewportView(messageList);
Questo funziona come add(component)
per JList e ottiene il suo comportamento intrinseco.
Per lo scorrimento automatico Sto usando un semplice concetto di variabile statica e list.makeVisible (int index)
public class autoScrollExample
{
static int index=0;
private void someFunction()
/*
*
*/
list1.add("element1");
list1.makeVisible(index++);
/*
*
*/
private void someOtherFunction()
/*
*
*/
list1.add("element2");
list1.makeVisible(index++);
/*
*
*/
}
Ho usato JScrollPane
con JTextArea
. Ho evitato la forza di scorrimento verso il basso per lo scorrimento solo quando il valore JScrollBar max
modificato:
JScrollPane scrollPane = new JScrollPane(jTextArea);
verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
scrollPane.getVerticalScrollBar().addAdjustmentListener(
e -> {
if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0)
return;
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
});
suppongo, non c'è soluzione migliore per filtrare gli eventi senza variabili aggiuntive, e gradirebbe se qualcuno post-it.
Credo che ciò che si vuole fare è avere lo scorrere verso il basso quando si aggiunge roba al vostro messageList, piuttosto che sulla regolazione. Quindi, il codice potrebbe essere la seguente:
Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom) sb.setValue(sb.getMaximum());
In caso contrario si avrebbe bisogno di dire se l'adeguamento è stato causato da un cambiamento del modello, o con il mouse, e guardando attraverso la documentazione API non sono sicuro se c'è un modo per farlo facilmente. Anche se si potrebbe vedere se il AdjustmentEvent.getAdjustmentType()
restituisce valori diversi in questi casi, se questo è vero allora si potrebbe semplicemente avere un'istruzione if nella classe interna anonima.
Un'altra cosa che si potrebbe provare sarebbe quello di avere un qualche variabile booleana che viene impostata quando si aggiunge qualcosa alla lista. Poi, nel gestore di controllare per vedere se è impostata la variabile. Se è così, si fa la regolazione (e disinserire la variabile) in caso contrario, lo si ignora. In questo modo, non ci sarà un solo scorrere verso il basso per voce di essere aggiunto alla lista.