J'ai cherché littéralement sur tout l'Internet et je n'ai pas trouvé de solution fonctionnelle à mon problème.
J'ai un JTable
à laquelle je veux changer dynamiquement les couleurs d'arrière-plan des éléments suivants plusieurs rangées sans affecter la couleur d'arrière-plan des autres rangées dont les couleurs auraient déjà été modifiées.
Le changement de couleur est déclenché par un actionListener
sur un JMenuItem
d'un ContextMenu
comme le montre l'illustration suivante :
Le code que j'ai essayé jusqu'à présent est le suivant :
JMenu highlightMenu = new JMenu("Highlight");
// Add null
for (Color color : Arrays.asList(Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA,
Color.PINK, Color.GRAY)) {
JMenuItem x = new JMenuItem();
x.setOpaque(true);
x.setBackground(color);
highlightMenu.add(x);
x.addHierarchyListener(e -> x.setText(tab.getTable()
.getValueAt(tab.getTable().getSelectedRow(), tab.getTable().getColumn("Server").getModelIndex()).toString()));
x.addActionListener(e -> IntStream.of(tab.getTable().getSelectedRows())
.forEach(row -> ((Component) tab.getTable().getModel().getValueAt(row, 0)).setBackground(color)));
// x.addActionListener(e -> {
// IntStream.of(tab.getTable().getSelectedRows())
// .forEach(r -> tab.getTable().setDefaultRenderer(Object.class, new
// DefaultTableCellRenderer() {
// @Override
// public Component getTableCellRendererComponent(JTable table, Object value,
// boolean isSelected,
// boolean hasFocus, int row, int column) {
// Component comp = super.getTableCellRendererComponent(table, value,
// isSelected, hasFocus, row, column);
// if (r == row) {
// comp.setBackground(color);
// } else {
// comp.setBackground(null);
// }
// return comp;
// }
// }));
// tab.getTable().repaint();
// });
}
Si quelqu'un a une solution qui fonctionne, veuillez la partager, ce serait vraiment apprécié !
EDIT 0 : J'ai nettoyé les éditions car elles étaient trop nombreuses, j'ai donc ajouté des chaînes de débogage et cette table ne se comporte pas du tout comme elle le devrait, veuillez voir la capture d'écran suivante :
Note : Je ne sais pas non plus pourquoi, mais il semble que la table soit itérée plusieurs fois (5) comme le montre la sortie ci-dessus, ce qui ne devrait pas être le cas, car chaque tableau de la table a été itéré. JMenuItem
a son propre écouteur d'événements... Et il ne doit être déclenché qu'une seule fois, en fonction de la couleur ou de l'élément de menu sélectionné...
Et le tableau qui en résulte :
A partir du code suivant :
for (Color color : Arrays.asList(Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA,
Color.PINK, Color.GRAY)) {
JMenuItem x = new JMenuItem();
x.setOpaque(true);
x.setBackground(color);
x.setForeground(Color.BLACK);
highlightMenu.add(x);
x.addHierarchyListener(e -> x.setText(tab.getTable()
.getValueAt(tab.getTable().getSelectedRow(), tab.getTable().getColumn("Server").getModelIndex()).toString()));
x.addActionListener(e -> {
IntStream.of(tab.getTable().getSelectedRows()).forEach(row -> this.highlightedRows.put(row, color)
// this.highlightedRows.put(row, Arrays.asList(Color.BLACK, color)
);
tab.getTable().setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
stdOut.println(String.format("%s -> %s", row, highlightedRows.get(row)));
if (highlightedRows.get(row) != null) {
stdOut.println("XXXXXXX");
component.setBackground(highlightedRows.get(row));
}
// if (!isSelected && highlightedRows.containsKey(row)) {
// component.setForeground(highlightedRows.get(row).get(0));
// component.setBackground(highlightedRows.get(row).get(1));
// }
return component;
}
});
});
}
Comme vous le voyez, quelque chose ne tourne pas rond ici...
EDIT N : Presque résolu ce problème avec le code suivant :
for (Color color : Arrays.asList(Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA,
Color.PINK, Color.GRAY)) {
final JMenuItem x = new JMenuItem();
x.setOpaque(true);
x.setBackground(color);
x.setForeground(Color.BLACK);
highlightMenu.add(x);
x.addHierarchyListener(e -> x.setText(tab.getTable()
.getValueAt(tab.getTable().getSelectedRow(), tab.getTable().getColumn("Server").getModelIndex()).toString()));
x.addActionListener(e -> {
IntStream.of(tab.getTable().getSelectedRows())
.forEach(row -> this.highlightedRows.put(row, Arrays.asList(Color.BLACK, color)));
// row -> this.highlightedRows.put(row, color)
tab.getTable().setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
final Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
column);
stdOut.println(String.format("%s -> %s", row, highlightedRows.get(row)));
if (highlightedRows.containsKey(row)) {
component.setForeground(highlightedRows.get(row).get(0));
component.setBackground(highlightedRows.get(row).get(1));
} else {
if (row % 2 == 0) {
component.setBackground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.background"));
} else {
component
.setBackground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.alternateRowColor"));
}
component.setForeground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.foreground"));
}
if (isSelected) {
component
.setForeground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.selectionForeground"));
component
.setBackground(javax.swing.UIManager.getLookAndFeelDefaults().getColor("Table.selectionBackground"));
}
return component;
}
});
});
}
La seule chose qui se passe maintenant est que l'écouteur d'événement est appelé plus d'une fois, voir l'EDIT précédent, si cela est résolu alors ce serait 100% résolu, merci à tous !