2010-01-25 21 views
13

J'ai le code suivant:JScrollPane et JList défilement automatique

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 pour relire un message, cela force un défilement vers le bas. Comment puis-je résoudre ce problème?

Répondre

10

Lors de l'ajout d'un nouveau message, appelez scrollRectToVisible() sur le JList en utilisant 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 pratique de faire de la taille préférée du JViewport un multiple entier de la hauteur du volet de message. Voir aussi: How to Use Scroll Panes.

Addendum: Cette discussion convaincante de Text Area Scrolling peut également vous être utile.

-1

Je pense que ce que vous voulez faire est de le faire défiler vers le bas lorsque vous ajoutez des éléments à votre liste de messages, plutôt que sur le réglage. 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 un façon de le faire facilement. Bien que vous puissiez voir si le AdjustmentEvent.getAdjustmentType() renvoie des valeurs différentes dans ces cas, si cela est vrai, vous pouvez simplement avoir une instruction if dans votre classe interne anonyme.

Une autre chose que vous pourriez essayer serait d'avoir une variable booléenne quelque part qui est définie lorsque vous ajoutez quelque chose à la liste. Ensuite, dans votre gestionnaire, vous vérifiez si la variable est définie. Si oui, vous effectuez l'ajustement (et supprimez la variable) sinon vous l'ignorez. De cette façon, il n'y aura qu'un seul défilement par élément ajouté à la liste.

+0

Le type d'ajustement est le même dans les deux cas. J'ai essayé ceci pour défiler vers le bas si un message est ajouté. Mais si je fais cela, le dernier message ajouté n'est pas visible. Il ne défile pas assez bas. Comment puis-je résoudre cela? – dododedodonl

+0

Hmm ... Eh bien, une chose que vous pourriez faire serait d'avoir une variable booléenne quelque part qui est définie lorsque vous ajoutez quelque chose à la liste. Ensuite, dans votre gestionnaire, vous vérifiez si la variable est définie. Si oui, vous effectuez l'ajustement (et supprimez la variable) sinon vous l'ignorez. De cette façon, il n'y aura qu'un seul défilement par élément ajouté à la liste. –

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

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 ici est que cela peut devenir un peu difficile à trouver un événement qui se déclenche après la mise à jour de ListModel, JList et JScrollPane. "

+0

Le lien est mort. Pouvez-vous le rafraîchir? –

0

Pour 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++); 
    /* 
    * 
    */ 


    } 
1

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

Ce changement est getMaximum()-getValue() Ensuite, il fonctionne selon les besoins. getMaximum() prend le scroller à son maximum; tandis que getValue() le prend partout où 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.