英文:
Can you have row selection and cell selection at the same time in Java Swing?
问题
我有一个 JTable,并且只想在点击表格中第一列的单元格时选择该单元格。当我点击其他任何列中的单元格时,我希望选择整行。我该如何实现这个?
英文:
I have a JTable and want to select the cell only when a cell in the first column of the table is clicked. When I click on a cell in any other column I want the entire row to be selected. How can I achieve this?
答案1
得分: 1
你需要实现接口 TableColumnModelListener 并将其添加到你的 JTable
的 TableColumnModel
中。
以下是一个示例代码。
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 {
// ...(略去了其余部分)
@Override
public void columnSelectionChanged(ListSelectionEvent event) {
if (!event.getValueIsAdjusting()) {
int selectedColumn = table.getSelectedColumn();
if (selectedColumn == 0) {
table.setColumnSelectionAllowed(true);
}
else {
table.setColumnSelectionAllowed(false);
}
}
}
// ...(略去了其余部分)
}
在这个代码片段中,我使用了一个自定义的 TableModel,但这并不是实现所需行为的必要条件。
你问题的答案在上述代码的以下部分。
- 实现
TableColumnModelListener
接口
public class TableSel implements Runnable, TableColumnModelListener {
- 在接口实现中,只需实现
columnSelectionChanged(ListSelectionEvent)
方法。其他方法可以为空。 - 将你的实现添加到
JTable
中
table = new JTable(model);
TableColumnModel tcm = table.getColumnModel();
tcm.addColumnModelListener(this);
需要注意的是,我还将选择模式设置为单选。
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JTable
有行选择和列选择两种模式。默认情况下启用行选择而不启用列选择。可以查看 setColumnSelectionAllowed() 和 setRowSelectionAllowed() 方法。当两者都设置为 true 时,选择单个单元格。仅启用行选择时,选择一个单元格将选择包含该单元格的整行。同样,当仅允许列选择时,选择一个单元格将选择整个列。
因此,基本上你想要切换列选择的开关。如果所选列是第一列,那么需要启用列选择,而对于其他任何列,需要禁用列选择。
英文:
You need to implement the interface TableColumnModelListener and add it to the TableColumnModel
of your JTable
.
Here is an example.
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];
}
}
I use a custom TableModel but it is not required in order to implement the behavior you desire.
The answer to your question is in the following parts of the above code.
- Implement interface
TableColumnModelListener
public class TableSel implements Runnable, TableColumnModelListener {
- In the implementation of the interface, you only need to implement method
columnSelectionChanged(ListSelectionEvent)
. The other methods can be empty. - Add your implementation to the
JTable
table = new JTable(model);
TableColumnModel tcm = table.getColumnModel();
tcm.addColumnModelListener(this);
Note that I also set the selection mode to single selection.
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
A JTable
has row selection and column selection. By default row selection is enabled and column selection is not. See methods setColumnSelectionAllowed() and setRowSelectionAllowed(). When both are set to true a single cell is selected. When only row selection is enabled, then selecting a cell selects the whole row containing that cell. Likewise when only column selection is allowed.
So basically you want to turn column selection on and off. If the selected column is the first column, then column selection needs to be enabled and for any other column it needs to be disabled.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论