JTable select multiple non-contiguous cells with ctrl+click combination

拈花ヽ惹草 提交于 2019-12-24 01:05:10

问题


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.

But when I select cells from different row, I get this

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!