Jtable cellRenderer меняет фон строки
Я пытался какое-то время и просматривал Интернет, чтобы найти решение, однако я потерпел неудачу. Я пытаюсь динамически изменять фон строки Jtable. Я создал arrayList, который хранит номера выбранных строк (добавляя их каждый раз, когда пользователь нажимает alt + щелчок по ячейке), и в моем собственном tableCellRenderer я добавил
for(Integer c: leftSelectedCells){
if(c.equals(row)){comp.setForeground(Color.red); }
else { comp.setForeground(Color.black);}
}
Он работает, для нескольких ячеек или некоторого времени, после которого выбранные столбцы возвращаются к своему первоначальному цвету, я проверил, целые числа все еще находятся в массиве, так что это не проблема, есть идеи, что может вызвать проблему?
2 ответа
Как уже предлагалось в комментариях выше, вам необходимо предоставить пользовательский рендер для всех необходимых столбцов. В качестве альтернативы вы можете переопределить JTable.prepareRenderer
установить фон в соответствии со списком затронутых строк. Рендеринг таблицы строк @camickr объясняет этот подход. Ниже приведен пример, в котором выделены строки, по которым щелкают мышь + клавиша Alt. Для простоты список выделенных строк сохраняется как свойство клиента.
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class TableHighlight {
TableHighlight() {
JFrame frame = new JFrame("TableHighlight");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Object[][] data = { { "Column 1", "Column 2" },
{ "Column 1", "Column 2" }, { "Column 1", "Column 2" },
{ "Column 1", "Column 2" } };
Object[] columnNames = { "Column 1", "Column 2" };
DefaultTableModel model = new DefaultTableModel(data, columnNames);
final JTable table = new JTable(model) {
@Override
public Component prepareRenderer(TableCellRenderer renderer,
int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
List<Integer> selectedRows = (List<Integer>) getClientProperty("highlightRows");
c.setBackground(selectedRows.contains(row) ? Color.cyan : getBackground());
return c;
}
};
table.putClientProperty("highlightRows", new ArrayList<Integer>());
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent evt) {
if (!evt.isAltDown())
return;
int row = table.rowAtPoint(evt.getPoint());
if (row == -1)
return;
List<Integer> selectedRows = (List<Integer>) table
.getClientProperty("highlightRows");
int index = selectedRows.indexOf(row);
if (index != -1)
selectedRows.remove(index);
else
selectedRows.add(row);
table.repaint();
}
});
frame.add(new JScrollPane(table));
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TableHighlight();
}
});
}
}
Я бы рекомендовал использовать CTRL для множественного выбора вместо ALT. Во-первых, любой пользователь, который хочет сделать множественный выбор, уже будет знать, как это сделать, потому что CTRL является де-факто стандартной клавишей-модификатором для множественного выбора. Во-вторых, вы получаете поведение, которое вы хотите бесплатно, без необходимости реализовывать что-то особенное (кроме, возможно, предпочитаемой вами цветовой схемы).
package com.example.table.multiselect;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class MultiRowTableSelect extends JFrame {
public MultiRowTableSelect() {
DefaultTableModel model = new DefaultTableModel(0, 3);
model.addRow(new Integer[]{1, 2, 3});
model.addRow(new Integer[]{4, 5, 6});
model.addRow(new Integer[]{7, 8, 9});
model.addRow(new Integer[]{10, 11, 12});
JTable tbl = new JTable(model);
tbl.setRowSelectionAllowed(true); // when you click a cell, the entire row will be highlighted
/* Assuming you want all cells to be rendered using the custom renderer
* unless otherwise overridden, you can simply set the JTable's default
* renderer. The implementation is so simple here that I'm just
* creating an anonymous subclass of DefaultTableCellRenderer.
*/
tbl.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (isSelected) {
c.setForeground(Color.RED); // you can set the foreground and/or background here
}
return c;
}
});
add(new JScrollPane(tbl), BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationByPlatform(true);
pack();
setSize(400, 200);
setVisible(true);
}
/**
* @param args
*/
public static void main(String[] args) {
new MultiRowTableSelect();
}
}