Jtable et lignes + colonnes fixées
Hi all,
Je suis coincé avec un point douloureux sur des JTables.
Je souhaite implémenter en Swing une des fonctionnalités d'Excel : celle de figer les volets.
Si vous ne connaissez pas, il s'agit de diviser la feuille en 4 parties :
- le coin supérieur gauche n'est jamais scrollable,
- le coin inférieur gauche est scrollable verticalement uniquement,
- le coin supérieur droit est scrollable horizontalement uniquement et
- le coin inférieur droit est scrollable verticalement et horizontalement.
En cherchant un peu sur le net, j'ai trouvé des tutos (http://www.java2s.com/Code/Java/Swin...umnExample.htm) qui m'a bien inspiré, mais je n'arrive pas à conclure.
L'idée, c'est d'utiliser le JScrollPane et ses différentes zones de dessins.
Voici le code la méthode qui crée mon composant :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
final Object[][] data = new Object[50][50]; //tableau de 50*50
final Object[] column = new Object[50];
final int rowFixed = 8; //les 8 premières lignes seront fixées
final int columnFixed = 2; // ainsi que les 2 premières colonnes
/**
* Creates and return the DataGrid panel
* @return JComponent : containing the grid
*/
private JComponent getGridPanel()
{
/******************************* Creation des données *****************************/
// entête de colonnes
for (int i = 0 ; i < 50 ; i++)
{
column[i] = "col_" + String.valueOf(i);
}
// données du tableau
for (int i = 0 ; i < 50 ; i++)
{
for (int j = 0 ; j < 50 ; j++)
{
data[i][j] = "R" + String.valueOf(i) + "C" + String.valueOf(j) ;
}
}
/******************************* Creation des Modèles du tableau *****************************/
// Model pour les lignes et colonnes fixées (coin sup gauche)
AbstractTableModel fixedRowColumnModel = new AbstractTableModel()
{
public int getColumnCount() {
return columnFixed; //on limite aux colonnes figées
}
public int getRowCount() {
return rowFixed; //on limite aux lignes figées
}
public String getColumnName(int col) {
return (String) column[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public void setValueAt(Object obj, int row, int col) {
data[row][col] = obj;
}
};
// Model pour les lignes fixées (coin sup droit)
AbstractTableModel fixedRowModel = new AbstractTableModel()
{
public int getColumnCount() {
return column.length - columnFixed; // on ne compte que les colonnes de cette partie là
public int getRowCount() {
return rowFixed;
}
public String getColumnName(int col) {
return (String) column[col + columnFixed]; //les indices de la zone commencent en 0,0, mais dans notre cas on tient compte de ce qui est figé
}
public Object getValueAt(int row, int col) {
return data[row][col + columnFixed];
}
public void setValueAt(Object obj, int row, int col) {
data[row][col + columnFixed] = obj;
}
public boolean CellEditable(int row, int col) {
return true;
}
};
// Model pour les colonnes fixées (coin inf gauche)
AbstractTableModel fixedColumnModel = new AbstractTableModel()
{
public int getColumnCount() {
return columnFixed;
}
public int getRowCount() {
return data.length - rowFixed ;
}
public String getColumnName(int col) {
return (String) column[col];
}
public Object getValueAt(int row, int col) {
return data[row + rowFixed][col];
}
public void setValueAt(Object obj, int row, int col) {
data[row + rowFixed][col] = obj;
}
public boolean CellEditable(int row, int col) {
return true;
}
};
// Model pour le reste de la table (coin inf droit)
AbstractTableModel model = new AbstractTableModel()
{
public int getColumnCount() {
return column.length - columnFixed;
}
public int getRowCount() {
return data.length - rowFixed;
}
public String getColumnName(int col) {
return (String) column[col + columnFixed];
}
public Object getValueAt(int row, int col) {
return data[row + rowFixed][col + columnFixed];
}
public void setValueAt(Object obj, int row, int col) {
data[row + rowFixed][col + columnFixed] = obj;
}
public boolean CellEditable(int row, int col) {
return true;
}
};
/******************************* Creation des différentes tables *****************************/
JTable fixedRowColumnTable = new JTable(fixedRowColumnModel);
JTable fixedColumnTable = new JTable(fixedColumnModel);
JTable fixedRowTable = new JTable(fixedRowModel);
JTable table = new JTable(model);
// on souhaite faire apparaitre les scrollbars en cas de besoin :
fixedRowColumnTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedRowTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedColumnTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
/******************************* La partie intéréssante ! *****************************/
//Le control complet : initialisé avec la partie inf droite
JScrollPane jsp = new JScrollPane(table);
// la partie sup gauche, completement figé
JViewport viewportRC = new JViewport();
viewportRC.setView(fixedRowColumnTable);
viewportRC.setPreferredSize(fixedRowColumnTable.getPreferredSize());
// la partie inf gauche droite
JViewport viewportC = new JViewport();
viewportC.setView(fixedColumnTable);
viewportC.setPreferredSize(fixedColumnTable.getPreferredSize());
// la partie sup droite
JViewport viewportR = new JViewport();
viewportR.setView(fixedRowTable);
viewportR.setPreferredSize(fixedRowTable.getPreferredSize());
/******************************* On affecte au JScrollPane *****************************/
jsp.setColumnHeader(viewportR); //on affecte en entête de colonnes les lignes figées
jsp.setRowHeader(viewportC); //on affecte en entête de lignes les colonnes figées
jsp.setCorner(JScrollPane.UPPER_LEFT_CORNER, viewportRC); // et enfin l'intersection des Lignes/Colonnes figées, dans le coin sup gauche.
/******************************* et on se sauve *****************************/
return jsp;
} |
ça se comporte relativement bien, sauf que je n'ai plus d'entêtes de colonnes (mais c'est bien normal, je les écrase avec mes tableaux, un petit renderer reglera le problème), mais surtout, voila le rendu affiché :
http://img858.imageshack.us/img858/2993/sanstitresc.png
On constate que les scrollbars sont bien positionnées, que ma zone sup gauche est bien positionnée, idem pour les 2 inférieures, mais alors la sup droite n'a pas bougé : c'est la ligne telle que construite au debut de la méthode.
En débug, je constate que je ne passe jamais dans la méthode "getValueAt" du (AbstractTableModel)fixedRowModel.
Et là où j'ai besoin de vous, c'est que je n'arrive pas à m'imaginer pourquoi....
Any idea ?
Notez bien que je suis nouveau (3 mois) en Java, j'ai éventuellement mal appréhendé ce point.
Bonne soirée à tous,
Manu.
(Etant préssé par le temps, demain, j'essayerais de manipuler 2 grilles conjointements, avec chacune les 2 1eres colonnes figées, c'est une autre approche de ma problèmatique, mais j'aimerais bien avoir l'explication de ce point !)