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?

War es hilfreich?

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.

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