Jscrollpane und JList Auto Scroll
-
22-09-2019 - |
Frage
Ich habe den nächsten Code:
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());
}
});
Es scrollt automatisch nach unten. Aber wenn ich versuche, wieder nach oben zu scrollen, um eine Nachricht erneut zu lesen, zwingt sie eine Schriftrolle nach unten. Wie kann ich das beheben?
Lösung
Wenn Sie eine neue Nachricht hinzufügen, rufen Sie bei scrollRectToVisible()
auf der JList
Verwendung einer Rectangle
Die gleichen Abmessungen wie die bevorzugte Größe Ihres Nachrichtenbereichs. Bei einer vertikalen Ausrichtung kann es bequem sein, die bevorzugte Größe des JScrollPane
's JViewport
ein integrales Vielfachen der Höhe des Nachrichtenbereichs. Siehe auch: So verwenden Sie Scrollscheiben.
Addendum: diese überzeugende Diskussion von Textbereich Scrollen kann auch hilfreich sein.
Andere Tipps
Ich fand das wirklich nützlich:http://forums.sun.com/thread.jspa?threadid=623669 (Post von 'Inopia')
Es funktioniert perfekt
Wie er sagt: "Das Problem hier ist, dass es ein bisschen schwierig werden kann, ein Ereignis zu finden, das sowohl nach dem Listmodel, JList als auch dem JSCROLLPane aktualisiert wurde."
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. Bitte ändern Sie Ihren Code von
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
}
});
zu
messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
e.getAdjustable().setValue(e.getAdjustable().getValue());
}
});
Das ist Veränderung getMaximum()
zu getValue()
Dann funktioniert es wie erforderlich. getMaximum()
nimmt den Scroller zu seinem Maximum; während getValue()
Nimmt es überall dort, wo Ereignis passiert.
Sie können es vermeiden, dieses Code -Stück zu verwenden, wenn Sie eine Zeile einfügen
messageScrollList.setViewportView(messageList);
Das funktioniert wie add(component)
für JList und erhält sein inhärentes Verhalten.
Zum automatischen Scrollen verwende ich ein sehr einfaches Konzept der statischen Variablen und 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++);
/*
*
*/
}
ich benutzte JScrollPane
mit JTextArea
. Ich vermied es, Kraft zu scrollen, indem ich nur dann scrollen würde, wenn JScrollBar max
Wert geändert:
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();
});
Ich nehme an, es gibt eine bessere Lösung, um Ereignisse ohne zusätzliche Variablen zu filtern, und würde sich freuen, wenn jemand es posten.
Ich denke, Sie möchten es nach unten scrollen lassen, wenn Sie Ihre Messgeristin eher bei der Anpassung hinzufügen. Ihr Code könnte also so aussehen:
Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom) sb.setValue(sb.getMaximum());
Andernfalls müssten Sie feststellen, ob die Anpassung durch eine Modelländerung oder durch die Maus verursacht wurde und ich mich nicht sicher ist, ob es eine Möglichkeit gibt, dies einfach zu tun. Obwohl Sie sehen konnten, ob die AdjustmentEvent.getAdjustmentType()
Gibt in diesen Fällen unterschiedliche Werte zurück. Wenn dies wahr ist, könnten Sie nur eine IF -Anweisung in Ihrer anonymen inneren Klasse haben.
Eine andere Sache, die Sie versuchen könnten, wäre, eine boolesche Variable irgendwo zu haben, die festgelegt wird, wenn Sie der Liste etwas hinzufügen. In Ihrem Handler überprüfen Sie dann, ob die Variable festgelegt ist. In diesem Fall stellen Sie die Einstellung (und verunsichern Sie die Variable), sonst ignorieren Sie sie. Auf diese Weise wird nur ein Scrollen pro Element zur Liste hinzugefügt.