Bonjour.
Je n'ai pas trouvé de "Short, Self Contained, Correct(, Compilable), Example" de JTable dont les cellules des rangées contiennent, dans quelques colonnes contigües, des JRadioButton et dont les groupes correspondent aux rangées. Je tente donc de le réaliser moi-même, mais ça coince quelque part. Y a-t-il un connaisseur en la matière qui puisse me conseiller ? Il s'agit quand même d'une fonction qui devrait intéresser quelques programmeurs en Java.
Voici d'abord mon code, en 4 fichiers, qui fonctionne à moitié :
1) TableTest2) MonModèleTable
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 /* But : * Un tableau de p. ex. 5 colonnes de cases contenant chacune un bouton-poussoir. * Les boutons-poussoirs sont regroupée et interagissent par rangée entière de la table. * Pas d'autre type d'élément dans chaque rangée et pas de rangée contenant un autre type * d'élément. */ package test_table; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.AbstractCellEditor; import javax.swing.JFrame; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; // main() import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; public class TestTable { private JFrame cadre; private JTable table; protected void initUI() { table = new JTable(new MonModèleTable()); short nbreColo = (short) table.getColumnCount(); table.setRowHeight(25); TableColumn col; for (int i = 0 ; i < nbreColo ; i++) { col = table.getColumnModel().getColumn(i); col.setCellEditor (new RendeurEditeur_CelluleBoutonRadio()); col.setCellRenderer(new RendeurEditeur_CelluleBoutonRadio()); } cadre = new JFrame(); cadre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cadre.add(new JScrollPane(table), BorderLayout.CENTER); cadre.pack(); cadre.setVisible(true); } /** * @param args the command line arguments * @throws ClassNotFoundException * @throws InstantiationException * @throws IllegalAccessException * @throws UnsupportedLookAndFeelException */ public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); SwingUtilities.invokeLater(new Runnable() { @Override public void run() // Implements method from java.lang.Runnable { new TestTable().initUI(); } } ); } private class RendeurEditeur_CelluleBoutonRadio extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener { private final JRadioButton radioButton; public RendeurEditeur_CelluleBoutonRadio() { this.radioButton = new JRadioButton(); radioButton.addActionListener(this); radioButton.setOpaque(false); } @Override public Component getTableCellRendererComponent(JTable table, Object valeur, boolean estSélectionné, boolean hasFocus, int row, int column) { radioButton.setSelected(Boolean.TRUE.equals(valeur)); return radioButton; } @Override public Component getTableCellEditorComponent(JTable table, Object valeur, boolean estSélectionné, int row, int column) { radioButton.setSelected(Boolean.TRUE.equals(valeur)); return radioButton; } @Override public void actionPerformed(ActionEvent e) { stopCellEditing(); } @Override public Object getCellEditorValue() { return radioButton.isSelected(); } } }3) GestionnObjetsDUneRangée
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 package test_table; import java.util.List; import java.util.ArrayList; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; // import javax.swing.ButtonGroup; import javax.swing.table.AbstractTableModel; class MonModèleTable extends AbstractTableModel implements PropertyChangeListener { // Contient et gère les rangées de boutons-poussoirs et leurs regroupements. private GestionnObjetsDUneRangée gestionn_DonnéesDUneRang; private final List<GestionnObjetsDUneRangée> gestionn_DonnéesTteLatable = new ArrayList<>(); public MonModèleTable() { super(); // AbstractTableModel() MonObjet objet; for (short idxRang = 0 ; idxRang < 6 ; idxRang++) { gestionn_DonnéesDUneRang = new GestionnObjetsDUneRangée(); for (short idxColo = 0 ; idxColo < 4 ; idxColo++) { objet = new MonObjet(idxRang, idxColo); gestionn_DonnéesDUneRang.ajoutObjetÀRangée(objet); /* Pour enregistrer 'MonModèleTable' comme 'listener' des messages envoyés par * chaque objet de la liste de 'gestionn_DonnéesDUneRang'. */ objet.getPropertyChangeSupport().addPropertyChangeListener(this); } /* Pour enregistrer 'this' (= MonModèleTable) comme 'listener' des * messages envoyés par l'objet ... * - vers lequel une propriété (gestionn_DonnéesDUneRang) de 'MonModèleTable'-même * fait référence et * - d'une classe (GestionnObjetsDUneRangée) possédant une propriété (suppoChangePropri) * référençant une instanciation de PropertyChangeSupport. Celle-ci ayant pour * argument l'objet de classe 'GestionnObjetsDUneRangée' même. */ gestionn_DonnéesDUneRang.suppoChangePropri.addPropertyChangeListener(this); gestionn_DonnéesTteLatable.add(gestionn_DonnéesDUneRang); } } /* Rem.: Identité de la rangée et de la colonne de l'objet (B-P) disponible dans * 'evt.getSource();'. */ @Override public void propertyChange(PropertyChangeEvent evt) { Object objet2 = evt.getSource(); if (objet2 == gestionn_DonnéesDUneRang) { if (evt.getPropertyName().equals("objecten")) // MonModèleTable { ((MonObjet) evt.getNewValue()).getPropertyChangeSupport().addPropertyChangeListener(this); } fireTableDataChanged(); } else if (objet2 instanceof MonObjet) { // Lorsqu'un autre bout-pouss d'une rangée a été sélectionné ("geselecteerd") // ? Lorsque (evt.propertyName = "dataVanEenRij") // int colon = gestionn_DonnéesDUneRang.getObjetsDUneRangée().indexOf((MonObjet) objet2); // MonObjet objet3 = (MonObjet) gestionn_DonnéesDUneRang.getObjetsDUneRangée().get(colon); short[] coordBP = ((MonObjet) objet2).getCoordBP(); fireTableRowsUpdated(coordBP[0], coordBP[0]); // [0] : rangée 2 x } } @Override public int getColumnCount() { return gestionn_DonnéesDUneRang.getObjetsDUneRangée().size(); } @Override public int getRowCount() { return gestionn_DonnéesTteLatable.size(); } public MonObjet getValueAt(int col) { return gestionn_DonnéesDUneRang.getObjetsDUneRangée().get(col); } // Implements method from javax.swing.table.TableModel @Override public Object getValueAt(int idxRang, int idxColo) { return getValueAt(idxColo).isSélectionné(); } // Cette méthode amène entre autre aussi idxRang2 et idxColo2 dans cette classe. // Overrides method from javax.swing.table.AbstractTableModel @Override public void setValueAt(Object bpActionné, int idxRang2, int idxColo2) { getValueAt(idxColo2).setSélectionné(Boolean.TRUE.equals(bpActionné)); } // Overrides method from javax.swing.table.AbstractTableModel @Override public boolean isCellEditable(int idxRang3, int idxColo3) { return true; } /** There must be a specification of a renderer for the cells for the table not to invoke the * table model's 'getColumnClass' method (which gets the data type of the column's cells). */ // Overrides method from javax.swing.table.AbstractTableModel @Override public Class<?> getColumnClass(int rang) { return Object.class; } Class<?> getClasseDeCellule(int idxRang, int idxColo) { // À modifier return Object.class; } // Overrides method from javax.swing.table.AbstractTableModel @Override public String getColumnName(int colo) { // Libellé des colonnes return "Col " + (colo + 1); } }4) Mon Objet
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 package test_table; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.List; import javax.swing.ButtonGroup; class GestionnObjetsDUneRangée { private final List<MonObjet> objetsDUneRangée = new ArrayList<>(); // private final ButtonGroup groupeHorizBoutRad = new ButtonGroup(); PropertyChangeSupport suppoChangePropri = new PropertyChangeSupport(this); // GestionnObjetsDUneRangée() { } public void ajoutObjetÀRangée(MonObjet objet) { objetsDUneRangée.add(objet); setGestionn_ObjetsDUneRangée2(objet); suppoChangePropri.firePropertyChange("objecten", null, objet); } public List<MonObjet> getObjetsDUneRangée() { return objetsDUneRangée; } // Met tous les boutons-poussoirs d'une rangée dans leurs états adéquats. public void miseàjourTousBP_Rangée(MonObjet myObject) { for (MonObjet obj : objetsDUneRangée) { obj.setSélectionné(myObject == obj); } } // - Méthode appelée explicitement par 'ajoutObjetÀRangée(...)' dans 'GestionnObjetsDUneRangée'. void setGestionn_ObjetsDUneRangée2(MonObjet monObjet) { monObjet.gestionn_ObjetsDUneRangée = this; monObjet.supportChangtPropri.firePropertyChange("dataVanEenRij", null, monObjet.gestionn_ObjetsDUneRangée); } GestionnObjetsDUneRangée getGestionn_ObjetsDUneRangée2(MonObjet monObjet) { return monObjet.gestionn_ObjetsDUneRangée; } }Problème : Des boutons-poussoirs des rangées inférieures changent d'état aussi.
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 package test_table; import java.beans.PropertyChangeSupport; /** * Bean */ class MonObjet { private boolean sélectionné; GestionnObjetsDUneRangée gestionn_ObjetsDUneRangée; final PropertyChangeSupport supportChangtPropri; short[] coordBP = new short[2]; // idxRang et idxColo de l'objet à Bouton-Poussoir MonObjet(short idxRang, short idxColo) { supportChangtPropri = new PropertyChangeSupport(this); coordBP[0] = idxRang; coordBP[1] = idxColo; } PropertyChangeSupport getPropertyChangeSupport() { return supportChangtPropri; } boolean isSélectionné() { return sélectionné; } // Appelée par positionnerSélectionné(objet) dans 'gestionn_DObjetsDUneRang'). void setSélectionné(boolean sélectionné2) { if (this.sélectionné != sélectionné2) { // Ne passe ici que s'il y a changement d'état. this.sélectionné = sélectionné2; if (sélectionné) { // Ne passe ici que si le b-p vient d'être actionné. // 'sélectionné' de l'objet est déjà 'true'. gestionn_ObjetsDUneRangée.miseàjourTousBP_Rangée(this); } supportChangtPropri.firePropertyChange("geselecteerd", !sélectionné, sélectionné); } } short[] getCoordBP() { return coordBP; } }
Raison : Dans 'MonModèleTable', dans 'void propertyChange(PropertyChangeEvent evt)', le 'gestionn_ObjetsDUneRangée' de 'objet2' est toujours celui de la dernière rangée.
Comment obtenir le bon 'gestionn_ObjetsDUneRangée', c à d qui correspond à la rangée du bouton-radio qui vient d'être actionné ?
Merci d'avance, les as.
Partager