Question

J'ai le code suivant:

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

Il défile automatique vers le bas. Mais, si j'essaie de revenir en arrière jusqu'à relire un message, il force un défilement vers le bas. Comment puis-je résoudre ce problème?

Était-ce utile?

La solution

Lors de l'ajout d'un nouveau message, appelez scrollRectToVisible() sur le JList à l'aide d'un Rectangle ayant les mêmes dimensions que la taille préférée de votre fenêtre de message. Étant donné une orientation verticale, il peut être utile de faire la taille préférée des JScrollPane est JViewport un multiple entier de la hauteur de la fenêtre de message. Voir aussi: Comment utiliser Scroll Feuillets .

Addendum: Cette discussion convaincante de Zone texte Scrolling peut être utile aussi.

Autres conseils

J'ai trouvé ce vraiment utile: http://forums.sun.com/thread.jspa?threadID=623669 (post par 'Inopia')
Il fonctionne parfaitement

Comme il le dit: « Le problème est que cela peut devenir un peu difficile de trouver un événement qui se déclenche après la fois ListModel, JList et JScrollPane ont été mis à jour. »

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 questionneur. S'il vous plaît changer votre code de

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    });

à

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getValue());  
        }
    }); 

C'est à changer getMaximum() getValue() Ensuite, il fonctionne selon les besoins. getMaximum() prend la barre de défilement à son maximum; tandis que getValue() prend chaque fois que l'événement se produit.

Vous pouvez éviter d'utiliser ce morceau de code tout à fait si vous mettez une ligne

messageScrollList.setViewportView(messageList);

Cela fonctionne comme add(component) pour JList et obtient son comportement inhérent.

Pour le défilement automatique J'utilise un concept très simple de la variable statique et 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++);
     /*
     *
     */


    }

je JScrollPane avec JTextArea. J'évitais défiler vers le bas la force en faisant défiler que lorsque la valeur de JScrollBar max changé:

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

Je suppose que, il y a une meilleure solution pour filtrer les événements sans variables supplémentaires, et apprécierait si quelqu'un l'afficher.

Je pense que ce que vous voulez faire est de la faire défiler vers le bas lorsque vous ajoutez des choses à votre MessageList, plutôt que sur l'ajustement. Donc, votre code pourrait ressembler à ceci:

Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom)  sb.setValue(sb.getMaximum());

Sinon, vous devrez dire si l'ajustement a été causé par un changement de modèle, ou par la souris, et en regardant à travers l'API docs Je ne sais pas s'il y a une façon de le faire facilement. Bien que vous puissiez voir si le

scroll top