使用图像呈现 JButton 以获取 JTable 中的 JCheckBox 行为不会更新我的 table
Rendering JButton to get the JCheckBox behavior in a JTable by using images does not update my table
我正在渲染一个带有图像的 JButton,基本上是为了模拟 JCheckBox 的行为。为什么我不直接让 JTable 来呈现 JCheckbox?仅仅是因为我需要更大的复选框,而且我无法调整它们的大小(据我所知)。
所以,我有自己的 table 单元格渲染器和编辑器。两者都在其上呈现 JButton 和复选框图像。我想要做的是将图像从选中图像更改为未选中图像(反之亦然)并更新单元格值(布尔值 true 或 false)。但是,出于某种原因,getCellEditorValue() 不会更新我的 table。所以,一旦我松开鼠标,它们的价值就会回到原来的价值。
任何帮助将不胜感激!非常感谢!
public class TableExample extends JFrame {
JScrollPane pane;
JPanel panel;
JTable table;
Object[][] data;
MyTableModel tm;
Renderer buttonColumn;
public TableExample(Object[][] data) throws IOException {
String[] columns = {"Column#1", "Column#2", "Column#3", "Column#4", "Column#5", "Column#6"};
this.data = data;
this.setPreferredSize(new Dimension(700, 500));
this.setMinimumSize(new Dimension(700, 500));
this.setMaximumSize(new Dimension(700, 500));
tm = new MyTableModel(this.data, columns);
this.table = new JTable(tm);
this.table.setRowHeight(50);
table.setDefaultRenderer(Boolean.class, new Renderer(this, table, 5));
table.setDefaultEditor(Boolean.class, new Editor(this, table, 5));
this.pane = new JScrollPane(this.table);
this.add(this.pane);
}
/**
*
* TABLE MODEL
*/
public class MyTableModel extends AbstractTableModel {
private Object[][] data;
private String[] columns;
public MyTableModel(Object[][] data, String[] columns) {
this.data = data;
this.columns = columns;
}
public void setColumns(String[] columns1) {
this.columns = columns1;
}
@Override
public int getRowCount() {
return this.data.length;
}
@Override
public int getColumnCount() {
return this.columns.length;
}
@Override
public String getColumnName(int columnIndex) {
return columns[columnIndex];
}
@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
public void setValueAt(String 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("--------------------------");
}
}
/**
*
* CELL RENDERER
*/
private class Renderer extends JButton implements TableCellRenderer {
ImageIcon check;
ImageIcon uncheck;
boolean isChecked;
public Renderer(JFrame frame, JTable table, int column) throws IOException {
Image checkI = ImageIO.read(getClass().getResource("ukbuttonblue.png"));
Image unCheckI = ImageIO.read(getClass().getResource("ukbuttonrev.png"));
this.setBorderPainted(false);
check = new ImageIcon(checkI);
uncheck = new ImageIcon(unCheckI);
}
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
this.isChecked = (boolean) value;
if (isChecked) {
setIcon(check);
} else {
setIcon(uncheck);
}
return this;
}
}
/**
*
* CELL EDITOR
*/
private class Editor extends AbstractCellEditor implements TableCellEditor, ActionListener {
private JButton editButton;
ImageIcon check;
ImageIcon uncheck;
boolean isChecked;
public Editor(JFrame frame, JTable table, int column) throws IOException {
editButton = new JButton();
editButton.addActionListener(this);
editButton.setBorderPainted(false);
Image checkI = ImageIO.read(getClass().getResource("check.png"));
Image unCheckI = ImageIO.read(getClass().getResource("uncheck.png"));
check = new ImageIcon(checkI);
uncheck = new ImageIcon(unCheckI);
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
this.isChecked = (boolean) value;
if (this.isChecked) {
editButton.setIcon(uncheck);
} else {
editButton.setIcon(check);
}
System.out.println("Edit " + isChecked);
return editButton;
}
@Override
public Object getCellEditorValue() {
System.out.println("giden " + isChecked);
return this.isChecked;
}
@Override
public void actionPerformed(ActionEvent e) {
if (this.isChecked) {
this.isChecked = false;
} else {
this.isChecked = true;
}
fireEditingStopped();
}
}
public static void main(String[] args) throws IOException {
Object[][] data = {
{"1", "Allan", "Smith", false, true, false},
{"2", "Jerry", "Tucker", true, false, true}
};
TableExample app = new TableExample(data);
app.setVisible(true);
}
}
经过一段时间的研究后,我意识到 myTableModel 的 isCellEditable 方法无法正常工作。我只是切换到 DetafultTableModel 覆盖获取列 class。
@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
使用 DefaultTableModel 的一个问题是布尔值 class 会自动呈现给常规 JCheckBoxes。因此,我没有使用布尔值 class,而是使用 Integer class 来简单地用 0 和 1 来模拟 true 和 false。
这是在 JTable 中使用按钮和图像模拟 JCheckBox 行为的最终程序。这为呈现不同图像提供了极大的灵活性,并且仍然获得 JCheckBox 行为。那么,尽情享受吧!
public class TableExample extends JFrame {
JScrollPane pane;
JPanel panel;
JTable table;
Object[][] data;
DefaultTableModel tm;
Renderer buttonColumn;
public TableExample(Object[][] data) throws IOException {
String[] columns = {"Column#1", "Column#2", "Column#3", "Column#4", "Column#5", "Column#6"};
this.data = data;
this.setPreferredSize(new Dimension(700, 500));
this.setMinimumSize(new Dimension(700, 500));
this.setMaximumSize(new Dimension(700, 500));
//tm = new DefaultTableModel(this.data, columns);
DefaultTableModel tm = new DefaultTableModel(this.data, columns) {
@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
};
this.table = new JTable(tm);
this.table.setRowHeight(50);
table.setDefaultRenderer(Integer.class, new Renderer(this, table, 5));
table.setDefaultEditor(Integer.class, new Editor(this, table, 5));
this.pane = new JScrollPane(this.table);
this.add(this.pane);
}
/**
*
* RENDERER
*/
private class Renderer extends JButton implements TableCellRenderer {
ImageIcon check;
ImageIcon uncheck;
int isChecked;
public Renderer(JFrame frame, JTable table, int column) throws IOException {
Image checkI = ImageIO.read(getClass().getResource("check.png"));
Image unCheckI = ImageIO.read(getClass().getResource("uncheck.png"));
this.setBorderPainted(false);
check = new ImageIcon(checkI);
uncheck = new ImageIcon(unCheckI);
}
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
this.isChecked = (int) value;
if (isChecked == 1) {
setIcon(check);
} else {
setIcon(uncheck);
}
return this;
}
}
/**
*
* EDITOR
*/
private class Editor extends AbstractCellEditor implements TableCellEditor, ActionListener {
private JButton editButton;
ImageIcon check;
ImageIcon uncheck;
int isChecked;
public Editor(JFrame frame, JTable table, int column) throws IOException {
editButton = new JButton();
editButton.addActionListener(this);
editButton.setBorderPainted(false);
Image checkI = ImageIO.read(getClass().getResource("check.png"));
Image unCheckI = ImageIO.read(getClass().getResource("uncheck.png"));
check = new ImageIcon(checkI);
uncheck = new ImageIcon(unCheckI);
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
this.isChecked = (int) value;
if (this.isChecked == 1) {
editButton.setIcon(uncheck);
this.isChecked = 0;
} else {
editButton.setIcon(check);
this.isChecked = 1;
}
return editButton;
}
@Override
public Object getCellEditorValue() {
return this.isChecked;
}
@Override
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
public void updateValue() {
}
}
public static void main(String[] args) throws IOException {
Object[][] data = {
{"1", "Allan", "Smith", false, false, 0},
{"2", "Jerry", "Tucker", true, true, 1}
};
TableExample app = new TableExample(data);
app.setVisible(true);
}
}
我正在渲染一个带有图像的 JButton,基本上是为了模拟 JCheckBox 的行为。为什么我不直接让 JTable 来呈现 JCheckbox?仅仅是因为我需要更大的复选框,而且我无法调整它们的大小(据我所知)。
所以,我有自己的 table 单元格渲染器和编辑器。两者都在其上呈现 JButton 和复选框图像。我想要做的是将图像从选中图像更改为未选中图像(反之亦然)并更新单元格值(布尔值 true 或 false)。但是,出于某种原因,getCellEditorValue() 不会更新我的 table。所以,一旦我松开鼠标,它们的价值就会回到原来的价值。
任何帮助将不胜感激!非常感谢!
public class TableExample extends JFrame {
JScrollPane pane;
JPanel panel;
JTable table;
Object[][] data;
MyTableModel tm;
Renderer buttonColumn;
public TableExample(Object[][] data) throws IOException {
String[] columns = {"Column#1", "Column#2", "Column#3", "Column#4", "Column#5", "Column#6"};
this.data = data;
this.setPreferredSize(new Dimension(700, 500));
this.setMinimumSize(new Dimension(700, 500));
this.setMaximumSize(new Dimension(700, 500));
tm = new MyTableModel(this.data, columns);
this.table = new JTable(tm);
this.table.setRowHeight(50);
table.setDefaultRenderer(Boolean.class, new Renderer(this, table, 5));
table.setDefaultEditor(Boolean.class, new Editor(this, table, 5));
this.pane = new JScrollPane(this.table);
this.add(this.pane);
}
/**
*
* TABLE MODEL
*/
public class MyTableModel extends AbstractTableModel {
private Object[][] data;
private String[] columns;
public MyTableModel(Object[][] data, String[] columns) {
this.data = data;
this.columns = columns;
}
public void setColumns(String[] columns1) {
this.columns = columns1;
}
@Override
public int getRowCount() {
return this.data.length;
}
@Override
public int getColumnCount() {
return this.columns.length;
}
@Override
public String getColumnName(int columnIndex) {
return columns[columnIndex];
}
@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
public void setValueAt(String 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("--------------------------");
}
}
/**
*
* CELL RENDERER
*/
private class Renderer extends JButton implements TableCellRenderer {
ImageIcon check;
ImageIcon uncheck;
boolean isChecked;
public Renderer(JFrame frame, JTable table, int column) throws IOException {
Image checkI = ImageIO.read(getClass().getResource("ukbuttonblue.png"));
Image unCheckI = ImageIO.read(getClass().getResource("ukbuttonrev.png"));
this.setBorderPainted(false);
check = new ImageIcon(checkI);
uncheck = new ImageIcon(unCheckI);
}
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
this.isChecked = (boolean) value;
if (isChecked) {
setIcon(check);
} else {
setIcon(uncheck);
}
return this;
}
}
/**
*
* CELL EDITOR
*/
private class Editor extends AbstractCellEditor implements TableCellEditor, ActionListener {
private JButton editButton;
ImageIcon check;
ImageIcon uncheck;
boolean isChecked;
public Editor(JFrame frame, JTable table, int column) throws IOException {
editButton = new JButton();
editButton.addActionListener(this);
editButton.setBorderPainted(false);
Image checkI = ImageIO.read(getClass().getResource("check.png"));
Image unCheckI = ImageIO.read(getClass().getResource("uncheck.png"));
check = new ImageIcon(checkI);
uncheck = new ImageIcon(unCheckI);
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
this.isChecked = (boolean) value;
if (this.isChecked) {
editButton.setIcon(uncheck);
} else {
editButton.setIcon(check);
}
System.out.println("Edit " + isChecked);
return editButton;
}
@Override
public Object getCellEditorValue() {
System.out.println("giden " + isChecked);
return this.isChecked;
}
@Override
public void actionPerformed(ActionEvent e) {
if (this.isChecked) {
this.isChecked = false;
} else {
this.isChecked = true;
}
fireEditingStopped();
}
}
public static void main(String[] args) throws IOException {
Object[][] data = {
{"1", "Allan", "Smith", false, true, false},
{"2", "Jerry", "Tucker", true, false, true}
};
TableExample app = new TableExample(data);
app.setVisible(true);
}
}
经过一段时间的研究后,我意识到 myTableModel 的 isCellEditable 方法无法正常工作。我只是切换到 DetafultTableModel 覆盖获取列 class。
@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
使用 DefaultTableModel 的一个问题是布尔值 class 会自动呈现给常规 JCheckBoxes。因此,我没有使用布尔值 class,而是使用 Integer class 来简单地用 0 和 1 来模拟 true 和 false。
这是在 JTable 中使用按钮和图像模拟 JCheckBox 行为的最终程序。这为呈现不同图像提供了极大的灵活性,并且仍然获得 JCheckBox 行为。那么,尽情享受吧!
public class TableExample extends JFrame {
JScrollPane pane;
JPanel panel;
JTable table;
Object[][] data;
DefaultTableModel tm;
Renderer buttonColumn;
public TableExample(Object[][] data) throws IOException {
String[] columns = {"Column#1", "Column#2", "Column#3", "Column#4", "Column#5", "Column#6"};
this.data = data;
this.setPreferredSize(new Dimension(700, 500));
this.setMinimumSize(new Dimension(700, 500));
this.setMaximumSize(new Dimension(700, 500));
//tm = new DefaultTableModel(this.data, columns);
DefaultTableModel tm = new DefaultTableModel(this.data, columns) {
@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
};
this.table = new JTable(tm);
this.table.setRowHeight(50);
table.setDefaultRenderer(Integer.class, new Renderer(this, table, 5));
table.setDefaultEditor(Integer.class, new Editor(this, table, 5));
this.pane = new JScrollPane(this.table);
this.add(this.pane);
}
/**
*
* RENDERER
*/
private class Renderer extends JButton implements TableCellRenderer {
ImageIcon check;
ImageIcon uncheck;
int isChecked;
public Renderer(JFrame frame, JTable table, int column) throws IOException {
Image checkI = ImageIO.read(getClass().getResource("check.png"));
Image unCheckI = ImageIO.read(getClass().getResource("uncheck.png"));
this.setBorderPainted(false);
check = new ImageIcon(checkI);
uncheck = new ImageIcon(unCheckI);
}
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
this.isChecked = (int) value;
if (isChecked == 1) {
setIcon(check);
} else {
setIcon(uncheck);
}
return this;
}
}
/**
*
* EDITOR
*/
private class Editor extends AbstractCellEditor implements TableCellEditor, ActionListener {
private JButton editButton;
ImageIcon check;
ImageIcon uncheck;
int isChecked;
public Editor(JFrame frame, JTable table, int column) throws IOException {
editButton = new JButton();
editButton.addActionListener(this);
editButton.setBorderPainted(false);
Image checkI = ImageIO.read(getClass().getResource("check.png"));
Image unCheckI = ImageIO.read(getClass().getResource("uncheck.png"));
check = new ImageIcon(checkI);
uncheck = new ImageIcon(unCheckI);
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
this.isChecked = (int) value;
if (this.isChecked == 1) {
editButton.setIcon(uncheck);
this.isChecked = 0;
} else {
editButton.setIcon(check);
this.isChecked = 1;
}
return editButton;
}
@Override
public Object getCellEditorValue() {
return this.isChecked;
}
@Override
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
public void updateValue() {
}
}
public static void main(String[] args) throws IOException {
Object[][] data = {
{"1", "Allan", "Smith", false, false, 0},
{"2", "Jerry", "Tucker", true, true, 1}
};
TableExample app = new TableExample(data);
app.setVisible(true);
}
}