Можете ли вы одновременно выбирать строки и ячейки в Java Swing?

#java #swing

#java #swing

Вопрос:

У меня есть JTable, и я хочу выбирать ячейку только при щелчке на ячейке в первом столбце таблицы. Когда я нажимаю на ячейку в любом другом столбце, я хочу, чтобы была выбрана вся строка. Как я могу этого добиться?

Комментарии:

1. Я бы сказал, что вам нужно будет обработать это в прослушивателе выбора .

Ответ №1:

Вам необходимо реализовать интерфейс TableColumnModelListener и добавить его в TableColumnModel свой JTable .

Вот пример.

 import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.time.LocalDate;
import java.time.Month;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class TableSel implements Runnable, TableColumnModelListener {
    private JFrame  frame;
    private JTable  table;

    @Override // java.lang.Runnable
    public void run() {
        showGui();
    }

    @Override // javax.swing.event.TableColumnModelListener
    public void columnAdded(TableColumnModelEvent event) {
        // Do nothing.
    }

    @Override // javax.swing.event.TableColumnModelListener
    public void columnRemoved(TableColumnModelEvent event) {
        // Do nothing.
    }

    @Override // javax.swing.event.TableColumnModelListener
    public void columnMoved(TableColumnModelEvent event) {
        // Do nothing.
    }

    @Override // javax.swing.event.TableColumnModelListener
    public void columnMarginChanged(ChangeEvent event) {
        // Do nothing.
    }

    @Override // javax.swing.event.TableColumnModelListener
    public void columnSelectionChanged(ListSelectionEvent event) {
        if (!event.getValueIsAdjusting()) {
            int selectedColumn = table.getSelectedColumn();
            if (selectedColumn == 0) {
                table.setColumnSelectionAllowed(true);
            }
            else {
                table.setColumnSelectionAllowed(false);
            }
        }
    }

    private JScrollPane createTable() {
        TableModel model = new CustoMod();
        table = new JTable(model);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        TableColumnModel tcm = table.getColumnModel();
        tcm.addColumnModelListener(this);
        JScrollPane scrollPane = new JScrollPane(table);
        return scrollPane;
    }

    private void showGui() {
        frame = new JFrame("Table");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(createTable(), BorderLayout.CENTER);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new TableSel());
    }
}

class CustoMod extends AbstractTableModel {
    private static final String[]  COLUMNS;
    private static final Object[][]  DATA;

    static {
        COLUMNS = new String[]{"Surname", "Name", "Games", "Goals", "Born"};
        DATA = new Object[][] {
            {"Rumney","Harold", 171, 28, LocalDate.of(1907, Month.MAY, 16)},
            {"Regan","Jack", 196, 3, LocalDate.of(1912, Month.SEPTEMBER, 12)},
            {"Coventry","Syd", 227, 62, LocalDate.of(1899, Month.JUNE, 13)},
            {"Picken","Billy", 212, 46, LocalDate.of(1956, Month.JUNE, 7)},
            {"Collier","Albert", 205, 54, LocalDate.of(1909, Month.JULY, 9)},
            {"Buckley","Nathan", 260, 263, LocalDate.of(1972, Month.JULY, 26)},
            {"Merrett","Thorold", 180, 148, LocalDate.of(1933, Month.SEPTEMBER, 30)},
            {"Rose","Bob", 152, 214, LocalDate.of(1928, Month.AUGUST, 07)},
            {"Millane","Darren", 147, 78, LocalDate.of(1965, Month.AUGUST, 9)},
            {"Fothergill","Des", 111, 337, LocalDate.of(1920, Month.JULY, 15)},
            {"Weideman","Murray", 180, 262, LocalDate.of(1936, Month.FEBRUARY, 16)},
            {"Lee","Dick", 230, 707, LocalDate.of(1899, Month.MARCH, 19)},
            {"Kyne","Phonse", 245, 237, LocalDate.of(1915, Month.OCTOBER, 29)},
            {"Coventry","Gordon", 306, 1299, LocalDate.of(1901, Month.SEPTEMBER, 25)},
            {"Daicos","Peter", 250, 549, LocalDate.of(1961, Month.SEPTEMBER, 20)},
            {"Thompson","Len", 268, 217, LocalDate.of(1947, Month.AUGUST, 27)},
            {"Tuddenham","Des", 182, 251, LocalDate.of(1943, Month.JANUARY, 29)},
            {"Collier","Harry", 253, 299, LocalDate.of(1907, Month.OCTOBER, 01)},
            {"Shaw","Tony", 313, 157, LocalDate.of(1960, Month.JULY, 23)},
            {"Richardson","Wayne", 277, 323, LocalDate.of(1946, Month.DECEMBER, 8)},
            {"Whelan","Marcus", 173, 31, LocalDate.of(1914, Month.JUNE, 27)},
            {"Brown","Gavin", 254, 195, LocalDate.of(1967, Month.SEPTEMBER, 25)},
        };
    }

    @Override
    public int getRowCount() {
        return DATA.length;
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        Class<?> theClass;
        switch (columnIndex) {
            case 0:
            case 1:
                theClass = String.class;
                break;
            case 2:
            case 3:
                theClass = Integer.class;
                break;
            case 4:
                theClass = LocalDate.class;
            default:
                theClass = Object.class;
        }
        return theClass;
    }

    @Override
    public int getColumnCount() {
        return COLUMNS.length;
    }

    @Override
    public String getColumnName(int column) {
        return COLUMNS[column];
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return DATA[rowIndex][columnIndex];
    }
}
  

Я использую пользовательскую табличную модель, но это не требуется для реализации желаемого поведения.

Ответ на ваш вопрос содержится в следующих частях приведенного выше кода.

  1. Реализовать интерфейс TableColumnModelListener
 public class TableSel implements Runnable, TableColumnModelListener {
  
  1. При реализации интерфейса вам нужно только реализовать метод columnSelectionChanged(ListSelectionEvent) . Другие методы могут быть пустыми.
  2. Добавьте свою реализацию в JTable
 table = new JTable(model);
TableColumnModel tcm = table.getColumnModel();
tcm.addColumnModelListener(this);
  

Обратите внимание, что я также установил режим выбора на одиночный выбор.

 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  

A JTable имеет выбор строки и выбор столбца. По умолчанию выбор строки включен, а выбор столбца — нет. Смотрите методы setColumnSelectionAllowed() и setRowSelectionAllowed() . Когда для обоих установлено значение true, выбирается одна ячейка. Когда включен только выбор строки, при выборе ячейки выбирается вся строка, содержащая эту ячейку. Аналогично, когда разрешен только выбор столбца.

Итак, в основном вы хотите включать и выключать выбор столбцов. Если выбранный столбец является первым столбцом, то необходимо включить выбор столбца, а для любого другого столбца его необходимо отключить.