这个问题非常具体。下面的代码是从Oracle JTable教程中提取的一个示例,其中添加了Select All复选框的代码,用于选择和取消选择最终列中的所有复选框。我被分配到的程序使用了与此类似的设置。这是一个工作示例,但有一个问题,我无法弄清楚如何修复。
当您对表格的最后一列中的一个单元格进行选择/聚焦并按下Alt + A(全部选择复选框的助记符)时,焦点对齐的单元格不会与另一个单元格进行渲染/更新列中的单元格。根本问题是:列是可编辑的,似乎当按下一个字符键时,它会混淆单元格更新的能力。如果你使单元格不可编辑并在焦点处于使用时使用助记符,它将正常工作,但是你不能用鼠标点击它。
我希望能够同时使用鼠标单击任何复选框单元格或全部选择按钮,并且还可以随时使用助记键进行全选按钮。
如果焦点位于复选框列中的单元格上,如何使用助记符选择全部时,如何使复选框单元格更新?
以下是完整的示例程序。
/*
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle or the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* TableDemo.java requires no other files.
*/
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
/**
* TableDemo is just like SimpleTableDemo, except that it
* uses a custom TableModel.
*/
public class TestJTable extends JPanel {
private static final long serialVersionUID = 1L;
public static JTable table;
private boolean DEBUG = false;
public JPanel tablePanel;
public TestJTable() {
super(new GridLayout(1,0));
table = new JTable(new MyTableModel());
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
JPanel selectAllCheckBoxPanel = new CreateSelectAllCheckBox();
tablePanel = new JPanel();
tablePanel.setLayout(new BorderLayout());
tablePanel.add(selectAllCheckBoxPanel, BorderLayout.PAGE_START);
tablePanel.add(scrollPane, BorderLayout.PAGE_END);
add(tablePanel);
}
class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
private Object[][] data = {
{"Kathy", "Smith",
"Snowboarding", new Integer(5), new Boolean(false)},
{"John", "Doe",
"Rowing", new Integer(3), new Boolean(true)},
{"Sue", "Black",
"Knitting", new Integer(2), new Boolean(false)},
{"Jane", "White",
"Speed reading", new Integer(20), new Boolean(true)},
{"Joe", "Brown",
"Pool", new Integer(10), new Boolean(false)}
};
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
/*
* JTable uses this method to determine the default renderer/
* editor for each cell. If we didn't implement this method,
* then the last column would contain text ("true"/"false"),
* rather than a check box.
*/
public Class <?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
/*
* Don't need to implement this method unless your table's
* editable.
*/
public boolean isCellEditable(int row, int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
if (col < 2) {
return false;
} else {
return true;
}
}
/*
* Don't need to implement this method unless your table's
* data can change.
*/
public void setValueAt(Object value, int row, int col) {
if (DEBUG) {
System.out.println("Setting value at " + row + "," + col
+ " to " + value
+ " (an instance of "
+ value.getClass() + ")");
}
data[row][col] = value;
fireTableCellUpdated(row, col);
if (DEBUG) {
System.out.println("New value of data:");
printDebugData();
}
}
private void printDebugData() {
int numRows = getRowCount();
int numCols = getColumnCount();
for (int i=0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j=0; j < numCols; j++) {
System.out.print(" " + data[i][j]);
}
System.out.println();
}
System.out.println("--------------------------");
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TestJTable newContentPane = new TestJTable();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
/**
* code to create the Select All check box at top of table.
*/
class CreateSelectAllCheckBox extends JPanel {
private static final long serialVersionUID = 1L;
public static JCheckBox selectAllCheckBox;
public CreateSelectAllCheckBox() {
selectAllCheckBox = new JCheckBox("Select All");
selectAllCheckBox.setFocusable(true);
selectAllCheckBox.setEnabled(true);
selectAllCheckBox.setSelected(false);
selectAllCheckBox.setOpaque(true);
selectAllCheckBox.setMnemonic(KeyEvent.VK_A);
selectAllCheckBox.addActionListener(new SelectAllActionListener());
this.setLayout(new BorderLayout());
this.add(selectAllCheckBox, BorderLayout.PAGE_START);
}
}
/**
* Listener for Select All check box. Will select all or unselect all check boxes in column 5 when toggled.
*/
class SelectAllActionListener implements ActionListener {
private static JTable table = TestJTable.table;
public void actionPerformed(ActionEvent e) {
if (CreateSelectAllCheckBox.selectAllCheckBox.isSelected()){
TableModel model = table.getModel();
for (int row = 0; row < model.getRowCount(); row++) {
model.setValueAt(Boolean.valueOf(true), row, 4);
}
}
if (!CreateSelectAllCheckBox.selectAllCheckBox.isSelected()){
TableModel model = table.getModel();
for (int row = 0; row < model.getRowCount(); row++) {
model.setValueAt(Boolean.valueOf(false), row, 4);
}
}
}
}
编辑以下 - 解决问题,将Listener类更改为以下代码。附加代码是在设置值之前调用cancelCellEditing()。在使用侦听器设置值后,它不会阻止单元格仍可编辑。谢谢Dodd10x代码:)
/**
* Listener for Select All check box. Will select all or unselect all check boxes in column 5 when toggled.
*/
class SelectAllActionListener implements ActionListener {
private static JTable table = TestJTable.table;
public void actionPerformed(ActionEvent e) {
TableCellEditor editor = table.getCellEditor();
if (editor != null) {
editor.cancelCellEditing();
}
if (CreateSelectAllCheckBox.selectAllCheckBox.isSelected()){
TableModel model = table.getModel();
for (int row = 0; row < model.getRowCount(); row++) {
model.setValueAt(Boolean.valueOf(true), row, 4);
}
}
if (!CreateSelectAllCheckBox.selectAllCheckBox.isSelected()){
TableModel model = table.getModel();
for (int row = 0; row < model.getRowCount(); row++) {
model.setValueAt(Boolean.valueOf(false), row, 4);
}
}
}
}
答案 0 :(得分:3)
您选择的单元格处于编辑状态,因此无法更新。在select / deselect all命令中,您需要先获取当前选定的单元格并告诉它停止编辑。
TableCellEditor editor = getCellEditor();
if (editor != null) {
editor.cancelCellEditing();
}