问题
I want to create a JTable that I'll be able to select multiple, non-contiguous cells with ctrl+click combination. So far, when I select not contiguous cells from the same row it works fine.
![](https://www.eimg.top/images/2020/03/25/7f13b06649c60e3434e0d9f9536f361b.jpg)
But when I select cells from different row, I get this
![](https://www.eimg.top/images/2020/03/25/de36862abd6f62120fe8df2e9037af5f.jpg)
Could somebofy please help me on this?
Here's my code
Class TestTimeTable
public class TestTimeTable extends JFrame{
private final int rows = 10;
private final int cols = 8;
private final String daysOfTheWeek[] = {"ΔΕΥΤΕΡΑ", "ΤΡΙΤΗ", "ΤΕΤΑΡΤΗ", "ΠΕΜΠΤΗ", "ΠΑΡΑΣΚΕΥΗ"};
private final JPanel jTablePanel;
private final JScrollPane scrollPane;
private final JTable timeTable;
private final Object[][] rowData;
public TestTimeTable(){
this.rowData = new Object[this.rows][this.cols];
this.timeTable = new JTable(this.rowData,this.daysOfTheWeek){
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
this.timeTable.setRowHeight(200, 200);
this.timeTable.setFillsViewportHeight(true);
this.timeTable.setOpaque(true);
this.timeTable.setColumnSelectionAllowed(true);
this.timeTable.setRowSelectionAllowed(true);
this.timeTable.setCellSelectionEnabled(true);
this.timeTable.setDefaultRenderer(Object.class, new BoardTableCellRenderer());
this.scrollPane = new JScrollPane(this.timeTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.jTablePanel = new JPanel();
this.jTablePanel.add(this.scrollPane);
getContentPane().add(new JScrollPane(this.timeTable), BorderLayout.CENTER);
}
public void createAndShowUI(){
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] argas){
TestTimeTable tt = new TestTimeTable();
tt.createAndShowUI();
}
Class BoardTableCellRenderer
class BoardTableCellRenderer extends DefaultTableCellRenderer{
Component c;
private static final long serialVersionUID = 1L;
private final Color selectionBlue = new Color(131,166,198);
private final MatteBorder border = new MatteBorder(1, 1, 0, 0, Color.BLACK);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (table.isCellSelected(row, column)){
c.setBackground(this.selectionBlue);
setBorder(this.border);
}
else {
c.setBackground(Color.WHITE);
}
return c;
}
}
Any opinion would be very helpful. Thank you in advance.
回答1:
Well this seems to be a common problem with JTables, you can not select non-contiguous cells but you can show "fake" non-contiguous cells.
You can check my solution but is not perfect. In that solution the "shift" selections doesn't work.
The idea is to override isCellSelected(int row, int colum) and changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) of JTable.
So I store the individually selected cells and use them in isCellSelected.
Create these classes fom cell storage :
class Cell {
private int row;
private int column;
public Cell(int row, int column) {
this.row = row;
this.column = column;
}
public boolean is(int r, int c) {
return row == r && column == c;
}
}
class CellSelectionSet {
private ArrayList<Cell> cells = new ArrayList<TestTimeTable.Cell>();
public void add(int r, int c) {
if (!contains(r, c)) {
cells.add(new Cell(r, c));
}
}
public boolean containsOneOrLess() {
return cells.size() <= 1;
}
public boolean contains(int r, int c) {
for (Cell cell : cells) {
if (cell.is(r, c)) {
return true;
}
}
return false;
}
public void clear() {
cells.clear();
}
}
and at JTable you can use that :
this.timeTable = new JTable(this.rowData, this.daysOfTheWeek) {
CellSelectionSet cellSelectionSet = new CellSelectionSet();
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
if (toggle) {
cellSelectionSet.add(rowIndex, columnIndex);
} else {
if (extend) {
cellSelectionSet.add(rowIndex, columnIndex);
} else {
// reset
cellSelectionSet.clear();
cellSelectionSet.add(rowIndex, columnIndex);
}
}
}
@Override
public boolean isCellSelected(int row, int column) {
if (cellSelectionSet.containsOneOrLess()) {
// show the default
return super.isCellSelected(row, column);
}
return cellSelectionSet.contains(row, column);
}
};
I hope this helps you.
来源:https://stackoverflow.com/questions/26032698/jtable-select-multiple-non-contiguous-cells-with-ctrlclick-combination