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 : Sélectionner tout - Visualiser dans une fenêtre à part
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é :



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 !)