2009-05-12 8 views
43

J'ai une JTable qui est dans un JScrollPane. Les lignes sont ajoutées à la table lors de l'exécution en fonction des événements qui se produisent dans mon application. Je veux que le volet Scoll défile au bas de la table lorsqu'une nouvelle ligne est ajoutée à la table.JTable défilement vers un index de ligne spécifié

Pour JLists Il existe le [ensureIndexIsVisible][1]() qui force un index particulier dans la liste à être visible. Je cherche la même chose mais pour un JTable. Il semble que je devrais déplacer manuellement la vue défilante sur le volet de défilement mais j'ai pensé qu'il devrait y avoir un moyen plus facile.

Répondre

33

Voir cet exemple: http://www.exampledepot.com/egs/javax.swing.table/Vis.html

mise à jour: le lien est maintenant obsolète, voici le code (de http://smi-protege.stanford.edu/repos/protege/protege-core/trunk/src/edu/stanford/smi/protege/util/ComponentUtilities.java)

public static void scrollToVisible(JTable table, int rowIndex, int vColIndex) { 
     if (!(table.getParent() instanceof JViewport)) { 
      return; 
     } 
     JViewport viewport = (JViewport)table.getParent(); 

     // This rectangle is relative to the table where the 
     // northwest corner of cell (0,0) is always (0,0). 
     Rectangle rect = table.getCellRect(rowIndex, vColIndex, true); 

     // The location of the viewport relative to the table 
     Point pt = viewport.getViewPosition(); 

     // Translate the cell location so that it is relative 
     // to the view, assuming the northwest corner of the 
     // view is (0,0) 
     rect.setLocation(rect.x-pt.x, rect.y-pt.y); 

     table.scrollRectToVisible(rect); 

     // Scroll the area into view 
     //viewport.scrollRectToVisible(rect); 
    } 
+0

Mauvais et beaucoup trop compliqué! Cela peut être fait en une seule ligne: – Elmue

+0

table.scrollRectToVisible (table.getCellRect (row, column, true)); – Elmue

4

JList utiliser en interne scrollRectToVisible et spécifier les coordonnées pour faire défiler. Je pense que vous devrez recoder une fonctionnalité similaire pour JTable.

65

C'est très facile, JTable a aussi la méthode scrollRectToVisible. Si vous voulez, vous pouvez essayer quelque chose comme ça pour faire scrollpane aller à au fond si un nouvel enregistrement est ajouté:

jTable1.getSelectionModel().setSelectionInterval(i, i); 
jTable1.scrollRectToVisible(new Rectangle(jTable1.getCellRect(i, 0, true))); 

i est le dernier enregistrement ajouté.

+1

Cela fonctionne bien, comme attendu, et fonctionne comme Ensureindexisvisible() (ou quelle que soit cette méthode) de Jlist. Le code marqué comme la réponse n'a pas fonctionné correctement. il n'a pas fait défiler tout le chemin jusqu'à l'index après qu'un 5-6 appelle une liste plus longue et n'affichait pas la ligne entière à chaque fois quand il faisait défiler. certaines rangées ont été coupées. Cela devrait être la réponse. – Bastiat

+1

Simple et fonctionne. Juste une question, quel est le but de la première ligne? Il semble que la deuxième ligne est suffisante. Btw, j'ai également eu besoin de faire défiler vers une colonne spécifique et cela fonctionne bien aussi en définissant le second paramètre de getCellRect. – Smig

+0

... et quel devrait être le sens du nouveau Rectangle()? getCellRect() renvoie déjà un rectangle! – Elmue

1

La première réponse fonctionne bien, mais la ligne sélectionnée est positionnée au bas de la table. J'ai donc créé cette version modifiée:

private void scrollToVisible(int rowIndex, int vColIndex) { 
     JTable table = getTablePanel().getTable(); 
     if (!(table.getParent() instanceof JViewport)) { 
      return; 
     } 
     if (table.getRowCount()<1){ 
      return; 
     } 
     JViewport viewport = (JViewport)table.getParent(); 
     // view dimension 
     Dimension dim = viewport.getExtentSize(); 
     // cell dimension 
     Dimension dimOne = new Dimension(0,0); 

     // This rectangle is relative to the table where the 
     // northwest corner of cell (0,0) is always (0,0). 
     Rectangle rect = table.getCellRect(rowIndex, vColIndex, true); 
     Rectangle rectOne; 
     if (rowIndex+1<table.getRowCount()) { 
      if (vColIndex+1<table.getColumnCount()) 
       vColIndex++; 
      rectOne = table.getCellRect(rowIndex+1, vColIndex, true); 
      dimOne.width=rectOne.x-rect.x; 
      dimOne.height=rectOne.y-rect.y; 
     } 

     // '+ veiw dimension - cell dimension' to set first selected row on the top 

     rect.setLocation(rect.x+dim.width-dimOne.width, rect.y+dim.height-dimOne.height); 

     table.scrollRectToVisible(rect); 
    } 

Maintenant, la ligne sélectionnée est positionnée en haut de la table.

+0

non, vous n'avez pas besoin de la fenêtre pour faire défiler n'importe où dans la table (tous les composants ont une méthode getVisibleRect) – kleopatra

0

Il me semble beaucoup plus facile de définir la position de la fenêtre au lieu de faire défiler la table. Voici mon code.

public void scrollCellToView(int rowIndex, int vColIndex) { 
    if (!(this.getParent() instanceof JViewport)) { 
     return; 
    } 
    JViewport viewport = (JViewport) this.getParent(); 
    Rectangle rect = this.getCellRect(rowIndex, vColIndex, true); 
    Rectangle viewRect = viewport.getViewRect(); 

    int x = viewRect.x; 
    int y = viewRect.y; 

    if (rect.x >= viewRect.x && rect.x <= (viewRect.x + viewRect.width - rect.width)){ 

    } else if (rect.x < viewRect.x){ 
     x = rect.x; 
    } else if (rect.x > (viewRect.x + viewRect.width - rect.width)) { 
     x = rect.x - viewRect.width + rect.width; 
    } 

    if (rect.y >= viewRect.y && rect.y <= (viewRect.y + viewRect.height - rect.height)){ 

    } else if (rect.y < viewRect.y){ 
     y = rect.y; 
    } else if (rect.y > (viewRect.y + viewRect.height - rect.height)){ 
     y = rect.y - viewRect.height + rect.height; 
    } 

    viewport.setViewPosition(new Point(x,y)); 
} 
+0

Cela semble très bien fonctionner! adapté ici: http://tinybrain.de/1004329 –

Questions connexes