如何恢复正常的 JTable 行选择?;撤消 table.setRowSelectionAllowed(假)
How to restore normal JTable row selection?; undo table.setRowSelectionAllowed(false)
描述
开始时 select 使用鼠标单击或键盘箭头编辑一行是可能的,selected 行与普通行一起着色 selection颜色.
用户可以select单行。
用户可以使用锁定按钮调用的代码锁定 selected 行。通过 模仿 一个 selected 行(我不确定这样做是否是正确的方法)使锁定本身成为可能,并通过两件事完成:
- 使用
DefaultTableCellRenderer
为 selected 行着色
- 禁用
JTable
行select离子setRowSelectionAllowed(false)
用户可以 unlock/restore 正常 selection 使用解锁按钮调用的代码。解锁简单来说就是撤销加锁的步骤:
- 使用
DefaultTableCellRenderer
移除 selected 行的颜色
- 启用
JTable
行select离子setRowSelectionAllowed(true)
<--(不起作用)
如何恢复正常的 JTable
行 selection?
SSCCE | MCVE 格式的代码
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class TableRowSelectionControl {
private JButton btnJTableSelectionLocked;
private JButton btnJTableSelectionUnlock;
private JPanel panelControl;
private JScrollPane scrollableTable;
private Integer selectedId;
private boolean lockedSelection;
private Color rowSelectionColor;
private Integer modelRow;
private JTable table;
private Object[][] data;
private JPanel createPanel() {
rowSelectionColor = new Color(184, 207, 229);
btnJTableSelectionLocked = new JButton("Lock selected row");
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionLocked.addActionListener(new BtnAction());
btnJTableSelectionUnlock = new JButton("Unlock selection");
btnJTableSelectionUnlock.setEnabled(false);
btnJTableSelectionUnlock.addActionListener(new BtnAction());
panelControl = new JPanel();
panelControl.add(btnJTableSelectionLocked);
panelControl.add(btnJTableSelectionUnlock);
DefaultTableModel model = new DefaultTableModel(new String[]{"Id", "Name", "State"}, 0) {
// Disable cell editing
@Override
public boolean isCellEditable(int row, int column) {
// Disable cells editing.
return false;
}
};
data = new Object[][]{
{1, "Alpha", true},
{5, "Beta", false},
{3, "Gama", true},
{4, "Giga", true},
{7, "Coca", true},};
table = new JTable(model);
table.getSelectionModel().setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new RowSelectionListener());
for (Object[] d : data) {
model.addRow(d);
}
JPanel containerPanel = new JPanel(new BorderLayout());
containerPanel.setPreferredSize(new Dimension(350, 200));
scrollableTable = new JScrollPane(table);
containerPanel.add(panelControl, BorderLayout.PAGE_START);
containerPanel.add(scrollableTable, BorderLayout.CENTER);
return containerPanel;
}
private class RowSelectionListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent event) {
// Ensure single event invoked
if (!event.getValueIsAdjusting() && !lockedSelection) {
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) event.getSource();
if (selectionModel.isSelectionEmpty()) {
// Empty selection: table row deselection occurred
btnJTableSelectionLocked.setEnabled(false);
} else {
btnJTableSelectionLocked.setEnabled(true);
int viewRow = table.getSelectedRow();
if (viewRow > -1) {
int idsColumn = 0;
modelRow = table.convertRowIndexToModel(viewRow);
Object selectedIdObject = table.getModel().getValueAt(modelRow, idsColumn);
selectedId = Integer.parseInt(selectedIdObject.toString());
}
}
}
}
}
private DefaultTableCellRenderer getRowsColorRenderer(Integer selectedId) {
DefaultTableCellRenderer renderer;
renderer = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent
= super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer id = (Integer) table.getModel().getValueAt(row, 0);
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
return tableCellRendererComponent;
}
};
return renderer;
}
private class BtnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object btnClicked = e.getSource();
int columnsSize = 3;
if (btnClicked == btnJTableSelectionLocked) {
lockedSelection = true;
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionUnlock.setEnabled(true);
table.setRowSelectionAllowed(false); // <-- Works fine.
for (int i = 0; i < columnsSize; i++) {
table.getColumnModel().getColumn(i).setCellRenderer(getRowsColorRenderer(selectedId));
}
} else if (btnClicked == btnJTableSelectionUnlock) {
lockedSelection = false;
btnJTableSelectionLocked.setEnabled(true);
btnJTableSelectionUnlock.setEnabled(false);
table.setRowSelectionAllowed(true); // <-- This line does not restore normal selection
for (int i = 0; i < columnsSize; i++) {
table.getColumnModel().getColumn(i).setCellRenderer(getRowsColorRenderer(null));
}
if (modelRow != null) {
// Enforce the same row to be selected on unloking;
// afterwords user can select any row.
table.setRowSelectionInterval(0, modelRow);
}
}
table.repaint();
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(() -> {
TableRowSelectionControl tableRowColorControl = new TableRowSelectionControl();
JFrame frame = new JFrame("TableRowSelectionControl");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(tableRowColorControl.createPanel());
frame.pack();
frame.setVisible(true);
});
}
}
你的问题出在你身上TableCellRenderer
以下...
Component tableCellRendererComponent
= super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
//...
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
正在覆盖 super
调用所做的选择颜色。
改为...
DefaultTableCellRenderer renderer;
renderer = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent
= super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer id = (Integer) table.getModel().getValueAt(row, 0);
System.out.println("id = " + id + "; selectedId = " + selectedId + "; isSelected = " + isSelected);
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else if (!isSelected) {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
return tableCellRendererComponent;
}
};
我可能建议的一件事是,不要切换单元格渲染器(这似乎不起作用),而是将单元格渲染器应用于 table 并使用 put/getClientProperty
JTable
的支持
private class BtnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object btnClicked = e.getSource();
int columnsSize = 3;
if (btnClicked == btnJTableSelectionLocked) {
System.out.println("Lock");
lockedSelection = true;
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionUnlock.setEnabled(true);
table.setRowSelectionAllowed(false); // <-- Works fine.
table.putClientProperty("selectedRowId", selectedId);
} else if (btnClicked == btnJTableSelectionUnlock) {
System.out.println("Unlock");
lockedSelection = false;
btnJTableSelectionLocked.setEnabled(true);
btnJTableSelectionUnlock.setEnabled(false);
table.setRowSelectionAllowed(true); // <-- This line does not restore normal selection
table.putClientProperty("selectedRowId", null);
}
}
}
和...
public class LockableTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer id = (Integer) table.getModel().getValueAt(row, 0);
Integer selectedId = (Integer) table.getClientProperty("selectedRowId");
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else if (!isSelected) {
setBackground(table.getBackground());
setForeground(table.getForeground());
setBorder(noFocusBorder);
}
return tableCellRendererComponent;
}
}
可运行示例...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class Test {
private JButton btnJTableSelectionLocked;
private JButton btnJTableSelectionUnlock;
private JPanel panelControl;
private JScrollPane scrollableTable;
private Integer selectedId;
private boolean lockedSelection;
private Color rowSelectionColor;
private Integer modelRow;
private JTable table;
private Object[][] data;
private JPanel createPanel() {
rowSelectionColor = new Color(184, 207, 229);
btnJTableSelectionLocked = new JButton("Lock selected row");
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionLocked.addActionListener(new BtnAction());
btnJTableSelectionUnlock = new JButton("Unlock selection");
btnJTableSelectionUnlock.setEnabled(false);
btnJTableSelectionUnlock.addActionListener(new BtnAction());
panelControl = new JPanel();
panelControl.add(btnJTableSelectionLocked);
panelControl.add(btnJTableSelectionUnlock);
DefaultTableModel model = new DefaultTableModel(new String[]{"Id", "Name", "State"}, 0) {
// Disable cell editing
@Override
public boolean isCellEditable(int row, int column) {
// Disable cells editing.
return false;
}
};
data = new Object[][]{
{1, "Alpha", true},
{5, "Beta", false},
{3, "Gama", true},
{4, "Giga", true},
{7, "Coca", true},};
table = new JTable(model);
TableColumnModel columnModel = table.getColumnModel();
LockableTableCellRenderer cellRenderer = new LockableTableCellRenderer();
for (int column = 0; column < columnModel.getColumnCount(); column++) {
columnModel.getColumn(column).setCellRenderer(cellRenderer);
}
table.getSelectionModel().setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new RowSelectionListener());
for (Object[] d : data) {
model.addRow(d);
}
JPanel containerPanel = new JPanel(new BorderLayout());
containerPanel.setPreferredSize(new Dimension(350, 200));
scrollableTable = new JScrollPane(table);
containerPanel.add(panelControl, BorderLayout.PAGE_START);
containerPanel.add(scrollableTable, BorderLayout.CENTER);
return containerPanel;
}
private class RowSelectionListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent event) {
// Ensure single event invoked
if (!event.getValueIsAdjusting() && !lockedSelection) {
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) event.getSource();
if (selectionModel.isSelectionEmpty()) {
// Empty selection: table row deselection occurred
btnJTableSelectionLocked.setEnabled(false);
} else {
btnJTableSelectionLocked.setEnabled(true);
int viewRow = table.getSelectedRow();
if (viewRow > -1) {
int idsColumn = 0;
modelRow = table.convertRowIndexToModel(viewRow);
Object selectedIdObject = table.getModel().getValueAt(modelRow, idsColumn);
selectedId = Integer.parseInt(selectedIdObject.toString());
}
}
}
}
}
private class BtnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object btnClicked = e.getSource();
int columnsSize = 3;
if (btnClicked == btnJTableSelectionLocked) {
System.out.println("Lock");
lockedSelection = true;
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionUnlock.setEnabled(true);
table.setRowSelectionAllowed(false); // <-- Works fine.
table.putClientProperty("selectedRowId", selectedId);
} else if (btnClicked == btnJTableSelectionUnlock) {
System.out.println("Unlock");
lockedSelection = false;
btnJTableSelectionLocked.setEnabled(true);
btnJTableSelectionUnlock.setEnabled(false);
table.setRowSelectionAllowed(true); // <-- This line does not restore normal selection
table.putClientProperty("selectedRowId", null);
}
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(() -> {
Test tableRowColorControl = new Test();
JFrame frame = new JFrame("TableRowSelectionControl");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(tableRowColorControl.createPanel());
frame.pack();
frame.setVisible(true);
});
}
public class LockableTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer id = (Integer) table.getModel().getValueAt(row, 0);
Integer selectedId = (Integer) table.getClientProperty("selectedRowId");
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else if (!isSelected) {
setBackground(table.getBackground());
setForeground(table.getForeground());
setBorder(noFocusBorder);
}
return tableCellRendererComponent;
}
}
}
来自 MadProgrammer 的优秀 。在这里,我只使用了很少的更新;供我参考和未来的访客。
不使用某些列值作为唯一标识符来跟踪所选行,而是使用 TableModel
行索引;那是行内容不可知解决方案。
当用户解锁所选行时;为了良好的用户体验,相同的选定行保持选中状态。
代码:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class TableRowSelectionControl {
private JButton btnJTableSelectionLock;
private JButton btnJTableSelectionUnlock;
private JPanel panelControl;
private JScrollPane scrollableTable;
private boolean lockedSelection;
private Color rowSelectionColor;
private final String selectedRowKey = "selectedRow";
private Integer selectedModelRow;
private Integer oldSelectedModelRow;
private JTable table;
private Object[][] data;
private JPanel createPanel() {
rowSelectionColor = new Color(184, 207, 229);
btnJTableSelectionLock = new JButton("Lock selected row");
btnJTableSelectionLock.setEnabled(false);
btnJTableSelectionLock.addActionListener(new BtnAction());
btnJTableSelectionUnlock = new JButton("Unlock selection");
btnJTableSelectionUnlock.setEnabled(false);
btnJTableSelectionUnlock.addActionListener(new BtnAction());
panelControl = new JPanel();
panelControl.add(btnJTableSelectionLock);
panelControl.add(btnJTableSelectionUnlock);
DefaultTableModel model = new DefaultTableModel(new String[]{"Id", "Name", "State"}, 0) {
// Disable cell editing
@Override
public boolean isCellEditable(int row, int column) {
// Disable cells editing.
return false;
}
};
data = new Object[][]{
{1, "Alpha", true},
{5, "Beta", false},
{3, "Gamma", true},
{4, "Giga", true},
{7, "Coca", true},};
table = new JTable(model);
TableColumnModel columnModel = table.getColumnModel();
LockableTableCellRenderer cellRenderer = new LockableTableCellRenderer();
for (int column = 0; column < columnModel.getColumnCount(); column++) {
columnModel.getColumn(column).setCellRenderer(cellRenderer);
}
table.getSelectionModel().setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new RowSelectionListener());
for (Object[] d : data) {
model.addRow(d);
}
JPanel containerPanel = new JPanel(new BorderLayout());
containerPanel.setPreferredSize(new Dimension(350, 200));
scrollableTable = new JScrollPane(table);
containerPanel.add(panelControl, BorderLayout.PAGE_START);
containerPanel.add(scrollableTable, BorderLayout.CENTER);
return containerPanel;
}
private class RowSelectionListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent event) {
// Ensure single event invoked
if (!event.getValueIsAdjusting() && !lockedSelection) {
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) event.getSource();
if (selectionModel.isSelectionEmpty()) {
// Empty selection: table row deselection occurred
btnJTableSelectionLock.setEnabled(false);
} else {
btnJTableSelectionLock.setEnabled(true);
int viewRow = table.getSelectedRow();
if (viewRow > -1) {
selectedModelRow = table.convertRowIndexToModel(viewRow);
}
}
}
}
}
private class BtnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object btnClicked = e.getSource();
if (btnClicked == btnJTableSelectionLock) {
System.out.println("Lock");
lockedSelection = true;
btnJTableSelectionLock.setEnabled(false);
btnJTableSelectionUnlock.setEnabled(true);
table.setRowSelectionAllowed(false);
oldSelectedModelRow = selectedModelRow;
table.putClientProperty(selectedRowKey, selectedModelRow);
} else if (btnClicked == btnJTableSelectionUnlock) {
System.out.println("Unlock");
lockedSelection = false;
btnJTableSelectionLock.setEnabled(true);
btnJTableSelectionUnlock.setEnabled(false);
table.setRowSelectionAllowed(true);
table.putClientProperty(selectedRowKey, null);
table.setRowSelectionInterval(0, oldSelectedModelRow);
}
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(() -> {
TableRowSelectionControl tableRowColorControl = new TableRowSelectionControl();
JFrame frame = new JFrame("TableRowSelectionControl");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(tableRowColorControl.createPanel());
frame.pack();
frame.setVisible(true);
});
}
public class LockableTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer renderedRow = table.convertRowIndexToModel(row);
Integer selectedRow = (Integer) table.getClientProperty(selectedRowKey);
if (selectedRow != null && renderedRow.equals(selectedRow)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else if (!isSelected) {
setBackground(table.getBackground());
setForeground(table.getForeground());
setBorder(noFocusBorder);
}
return tableCellRendererComponent;
}
}
}
描述
开始时 select 使用鼠标单击或键盘箭头编辑一行是可能的,selected 行与普通行一起着色 selection颜色.
用户可以select单行。
用户可以使用锁定按钮调用的代码锁定 selected 行。通过 模仿 一个 selected 行(我不确定这样做是否是正确的方法)使锁定本身成为可能,并通过两件事完成:
- 使用
DefaultTableCellRenderer
为 selected 行着色
- 禁用
JTable
行select离子setRowSelectionAllowed(false)
- 使用
用户可以 unlock/restore 正常 selection 使用解锁按钮调用的代码。解锁简单来说就是撤销加锁的步骤:
- 使用
DefaultTableCellRenderer
移除 selected 行的颜色
- 启用
JTable
行select离子setRowSelectionAllowed(true)
<--(不起作用)
- 使用
如何恢复正常的 JTable
行 selection?
SSCCE | MCVE 格式的代码
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class TableRowSelectionControl {
private JButton btnJTableSelectionLocked;
private JButton btnJTableSelectionUnlock;
private JPanel panelControl;
private JScrollPane scrollableTable;
private Integer selectedId;
private boolean lockedSelection;
private Color rowSelectionColor;
private Integer modelRow;
private JTable table;
private Object[][] data;
private JPanel createPanel() {
rowSelectionColor = new Color(184, 207, 229);
btnJTableSelectionLocked = new JButton("Lock selected row");
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionLocked.addActionListener(new BtnAction());
btnJTableSelectionUnlock = new JButton("Unlock selection");
btnJTableSelectionUnlock.setEnabled(false);
btnJTableSelectionUnlock.addActionListener(new BtnAction());
panelControl = new JPanel();
panelControl.add(btnJTableSelectionLocked);
panelControl.add(btnJTableSelectionUnlock);
DefaultTableModel model = new DefaultTableModel(new String[]{"Id", "Name", "State"}, 0) {
// Disable cell editing
@Override
public boolean isCellEditable(int row, int column) {
// Disable cells editing.
return false;
}
};
data = new Object[][]{
{1, "Alpha", true},
{5, "Beta", false},
{3, "Gama", true},
{4, "Giga", true},
{7, "Coca", true},};
table = new JTable(model);
table.getSelectionModel().setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new RowSelectionListener());
for (Object[] d : data) {
model.addRow(d);
}
JPanel containerPanel = new JPanel(new BorderLayout());
containerPanel.setPreferredSize(new Dimension(350, 200));
scrollableTable = new JScrollPane(table);
containerPanel.add(panelControl, BorderLayout.PAGE_START);
containerPanel.add(scrollableTable, BorderLayout.CENTER);
return containerPanel;
}
private class RowSelectionListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent event) {
// Ensure single event invoked
if (!event.getValueIsAdjusting() && !lockedSelection) {
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) event.getSource();
if (selectionModel.isSelectionEmpty()) {
// Empty selection: table row deselection occurred
btnJTableSelectionLocked.setEnabled(false);
} else {
btnJTableSelectionLocked.setEnabled(true);
int viewRow = table.getSelectedRow();
if (viewRow > -1) {
int idsColumn = 0;
modelRow = table.convertRowIndexToModel(viewRow);
Object selectedIdObject = table.getModel().getValueAt(modelRow, idsColumn);
selectedId = Integer.parseInt(selectedIdObject.toString());
}
}
}
}
}
private DefaultTableCellRenderer getRowsColorRenderer(Integer selectedId) {
DefaultTableCellRenderer renderer;
renderer = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent
= super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer id = (Integer) table.getModel().getValueAt(row, 0);
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
return tableCellRendererComponent;
}
};
return renderer;
}
private class BtnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object btnClicked = e.getSource();
int columnsSize = 3;
if (btnClicked == btnJTableSelectionLocked) {
lockedSelection = true;
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionUnlock.setEnabled(true);
table.setRowSelectionAllowed(false); // <-- Works fine.
for (int i = 0; i < columnsSize; i++) {
table.getColumnModel().getColumn(i).setCellRenderer(getRowsColorRenderer(selectedId));
}
} else if (btnClicked == btnJTableSelectionUnlock) {
lockedSelection = false;
btnJTableSelectionLocked.setEnabled(true);
btnJTableSelectionUnlock.setEnabled(false);
table.setRowSelectionAllowed(true); // <-- This line does not restore normal selection
for (int i = 0; i < columnsSize; i++) {
table.getColumnModel().getColumn(i).setCellRenderer(getRowsColorRenderer(null));
}
if (modelRow != null) {
// Enforce the same row to be selected on unloking;
// afterwords user can select any row.
table.setRowSelectionInterval(0, modelRow);
}
}
table.repaint();
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(() -> {
TableRowSelectionControl tableRowColorControl = new TableRowSelectionControl();
JFrame frame = new JFrame("TableRowSelectionControl");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(tableRowColorControl.createPanel());
frame.pack();
frame.setVisible(true);
});
}
}
你的问题出在你身上TableCellRenderer
以下...
Component tableCellRendererComponent
= super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
//...
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
正在覆盖 super
调用所做的选择颜色。
改为...
DefaultTableCellRenderer renderer;
renderer = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent
= super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer id = (Integer) table.getModel().getValueAt(row, 0);
System.out.println("id = " + id + "; selectedId = " + selectedId + "; isSelected = " + isSelected);
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else if (!isSelected) {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
return tableCellRendererComponent;
}
};
我可能建议的一件事是,不要切换单元格渲染器(这似乎不起作用),而是将单元格渲染器应用于 table 并使用 put/getClientProperty
JTable
private class BtnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object btnClicked = e.getSource();
int columnsSize = 3;
if (btnClicked == btnJTableSelectionLocked) {
System.out.println("Lock");
lockedSelection = true;
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionUnlock.setEnabled(true);
table.setRowSelectionAllowed(false); // <-- Works fine.
table.putClientProperty("selectedRowId", selectedId);
} else if (btnClicked == btnJTableSelectionUnlock) {
System.out.println("Unlock");
lockedSelection = false;
btnJTableSelectionLocked.setEnabled(true);
btnJTableSelectionUnlock.setEnabled(false);
table.setRowSelectionAllowed(true); // <-- This line does not restore normal selection
table.putClientProperty("selectedRowId", null);
}
}
}
和...
public class LockableTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer id = (Integer) table.getModel().getValueAt(row, 0);
Integer selectedId = (Integer) table.getClientProperty("selectedRowId");
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else if (!isSelected) {
setBackground(table.getBackground());
setForeground(table.getForeground());
setBorder(noFocusBorder);
}
return tableCellRendererComponent;
}
}
可运行示例...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class Test {
private JButton btnJTableSelectionLocked;
private JButton btnJTableSelectionUnlock;
private JPanel panelControl;
private JScrollPane scrollableTable;
private Integer selectedId;
private boolean lockedSelection;
private Color rowSelectionColor;
private Integer modelRow;
private JTable table;
private Object[][] data;
private JPanel createPanel() {
rowSelectionColor = new Color(184, 207, 229);
btnJTableSelectionLocked = new JButton("Lock selected row");
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionLocked.addActionListener(new BtnAction());
btnJTableSelectionUnlock = new JButton("Unlock selection");
btnJTableSelectionUnlock.setEnabled(false);
btnJTableSelectionUnlock.addActionListener(new BtnAction());
panelControl = new JPanel();
panelControl.add(btnJTableSelectionLocked);
panelControl.add(btnJTableSelectionUnlock);
DefaultTableModel model = new DefaultTableModel(new String[]{"Id", "Name", "State"}, 0) {
// Disable cell editing
@Override
public boolean isCellEditable(int row, int column) {
// Disable cells editing.
return false;
}
};
data = new Object[][]{
{1, "Alpha", true},
{5, "Beta", false},
{3, "Gama", true},
{4, "Giga", true},
{7, "Coca", true},};
table = new JTable(model);
TableColumnModel columnModel = table.getColumnModel();
LockableTableCellRenderer cellRenderer = new LockableTableCellRenderer();
for (int column = 0; column < columnModel.getColumnCount(); column++) {
columnModel.getColumn(column).setCellRenderer(cellRenderer);
}
table.getSelectionModel().setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new RowSelectionListener());
for (Object[] d : data) {
model.addRow(d);
}
JPanel containerPanel = new JPanel(new BorderLayout());
containerPanel.setPreferredSize(new Dimension(350, 200));
scrollableTable = new JScrollPane(table);
containerPanel.add(panelControl, BorderLayout.PAGE_START);
containerPanel.add(scrollableTable, BorderLayout.CENTER);
return containerPanel;
}
private class RowSelectionListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent event) {
// Ensure single event invoked
if (!event.getValueIsAdjusting() && !lockedSelection) {
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) event.getSource();
if (selectionModel.isSelectionEmpty()) {
// Empty selection: table row deselection occurred
btnJTableSelectionLocked.setEnabled(false);
} else {
btnJTableSelectionLocked.setEnabled(true);
int viewRow = table.getSelectedRow();
if (viewRow > -1) {
int idsColumn = 0;
modelRow = table.convertRowIndexToModel(viewRow);
Object selectedIdObject = table.getModel().getValueAt(modelRow, idsColumn);
selectedId = Integer.parseInt(selectedIdObject.toString());
}
}
}
}
}
private class BtnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object btnClicked = e.getSource();
int columnsSize = 3;
if (btnClicked == btnJTableSelectionLocked) {
System.out.println("Lock");
lockedSelection = true;
btnJTableSelectionLocked.setEnabled(false);
btnJTableSelectionUnlock.setEnabled(true);
table.setRowSelectionAllowed(false); // <-- Works fine.
table.putClientProperty("selectedRowId", selectedId);
} else if (btnClicked == btnJTableSelectionUnlock) {
System.out.println("Unlock");
lockedSelection = false;
btnJTableSelectionLocked.setEnabled(true);
btnJTableSelectionUnlock.setEnabled(false);
table.setRowSelectionAllowed(true); // <-- This line does not restore normal selection
table.putClientProperty("selectedRowId", null);
}
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(() -> {
Test tableRowColorControl = new Test();
JFrame frame = new JFrame("TableRowSelectionControl");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(tableRowColorControl.createPanel());
frame.pack();
frame.setVisible(true);
});
}
public class LockableTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer id = (Integer) table.getModel().getValueAt(row, 0);
Integer selectedId = (Integer) table.getClientProperty("selectedRowId");
if (selectedId != null && id.equals(selectedId)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else if (!isSelected) {
setBackground(table.getBackground());
setForeground(table.getForeground());
setBorder(noFocusBorder);
}
return tableCellRendererComponent;
}
}
}
来自 MadProgrammer 的优秀
不使用某些列值作为唯一标识符来跟踪所选行,而是使用
TableModel
行索引;那是行内容不可知解决方案。当用户解锁所选行时;为了良好的用户体验,相同的选定行保持选中状态。
代码:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class TableRowSelectionControl {
private JButton btnJTableSelectionLock;
private JButton btnJTableSelectionUnlock;
private JPanel panelControl;
private JScrollPane scrollableTable;
private boolean lockedSelection;
private Color rowSelectionColor;
private final String selectedRowKey = "selectedRow";
private Integer selectedModelRow;
private Integer oldSelectedModelRow;
private JTable table;
private Object[][] data;
private JPanel createPanel() {
rowSelectionColor = new Color(184, 207, 229);
btnJTableSelectionLock = new JButton("Lock selected row");
btnJTableSelectionLock.setEnabled(false);
btnJTableSelectionLock.addActionListener(new BtnAction());
btnJTableSelectionUnlock = new JButton("Unlock selection");
btnJTableSelectionUnlock.setEnabled(false);
btnJTableSelectionUnlock.addActionListener(new BtnAction());
panelControl = new JPanel();
panelControl.add(btnJTableSelectionLock);
panelControl.add(btnJTableSelectionUnlock);
DefaultTableModel model = new DefaultTableModel(new String[]{"Id", "Name", "State"}, 0) {
// Disable cell editing
@Override
public boolean isCellEditable(int row, int column) {
// Disable cells editing.
return false;
}
};
data = new Object[][]{
{1, "Alpha", true},
{5, "Beta", false},
{3, "Gamma", true},
{4, "Giga", true},
{7, "Coca", true},};
table = new JTable(model);
TableColumnModel columnModel = table.getColumnModel();
LockableTableCellRenderer cellRenderer = new LockableTableCellRenderer();
for (int column = 0; column < columnModel.getColumnCount(); column++) {
columnModel.getColumn(column).setCellRenderer(cellRenderer);
}
table.getSelectionModel().setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new RowSelectionListener());
for (Object[] d : data) {
model.addRow(d);
}
JPanel containerPanel = new JPanel(new BorderLayout());
containerPanel.setPreferredSize(new Dimension(350, 200));
scrollableTable = new JScrollPane(table);
containerPanel.add(panelControl, BorderLayout.PAGE_START);
containerPanel.add(scrollableTable, BorderLayout.CENTER);
return containerPanel;
}
private class RowSelectionListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent event) {
// Ensure single event invoked
if (!event.getValueIsAdjusting() && !lockedSelection) {
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) event.getSource();
if (selectionModel.isSelectionEmpty()) {
// Empty selection: table row deselection occurred
btnJTableSelectionLock.setEnabled(false);
} else {
btnJTableSelectionLock.setEnabled(true);
int viewRow = table.getSelectedRow();
if (viewRow > -1) {
selectedModelRow = table.convertRowIndexToModel(viewRow);
}
}
}
}
}
private class BtnAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object btnClicked = e.getSource();
if (btnClicked == btnJTableSelectionLock) {
System.out.println("Lock");
lockedSelection = true;
btnJTableSelectionLock.setEnabled(false);
btnJTableSelectionUnlock.setEnabled(true);
table.setRowSelectionAllowed(false);
oldSelectedModelRow = selectedModelRow;
table.putClientProperty(selectedRowKey, selectedModelRow);
} else if (btnClicked == btnJTableSelectionUnlock) {
System.out.println("Unlock");
lockedSelection = false;
btnJTableSelectionLock.setEnabled(true);
btnJTableSelectionUnlock.setEnabled(false);
table.setRowSelectionAllowed(true);
table.putClientProperty(selectedRowKey, null);
table.setRowSelectionInterval(0, oldSelectedModelRow);
}
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(() -> {
TableRowSelectionControl tableRowColorControl = new TableRowSelectionControl();
JFrame frame = new JFrame("TableRowSelectionControl");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(tableRowColorControl.createPanel());
frame.pack();
frame.setVisible(true);
});
}
public class LockableTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Integer renderedRow = table.convertRowIndexToModel(row);
Integer selectedRow = (Integer) table.getClientProperty(selectedRowKey);
if (selectedRow != null && renderedRow.equals(selectedRow)) {
setBackground(rowSelectionColor);
setForeground(table.getForeground());
} else if (!isSelected) {
setBackground(table.getBackground());
setForeground(table.getForeground());
setBorder(noFocusBorder);
}
return tableCellRendererComponent;
}
}
}