模型修改后充满文件的 JTable 重复值 (AbstractTableModel)
JTable filled with files repeats value after model modification (AbstractTableModel)
我又在和 JTable 纠缠了,我很卡。
问题是:
- 我有一个 select 文件路径的按钮来填充我的 JTable 的第一列:这工作正常。
- 单击一个复选框,我更改 jtable 的结构以添加或删除列:这工作正常。
- 当我再次尝试用文件路径填充新 table 时,只有最后一个 selected 被复制到列的每一行中。
我发现很多帖子都有类似的问题,但无法解决(尝试 cellRenderer、cellEditor、修改模型等)。下面我尽量把代码精简到最简单。我尝试了很多不同的东西,但我真的不明白发生了什么事的逻辑(我完整地阅读了文档,但显然我遗漏了一些东西)。
我也试过用DefaultTableModel做一个版本,但问题似乎是独立的。此外,我想保留 AbstractTableModel 因为其他 类 使用它。我认为模型中出现了问题,但我不知道是什么(在模型中也尝试了不同的火***)。
如果您看到错误并能解释其背后的逻辑,将不胜感激。
非常感谢。这是我认为不言自明的代码:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
public class FillTableExample extends JFrame {
private JLabel label = new JLabel("File:");
private JButton selectButton = new JButton("Select");
private JPanel labelButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
private Object rowDataTable[][] = {{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""}};
private String[] columnNames = {"File", "Name"};
private CustomTableModel fileTableModel = new CustomTableModel(rowDataTable, columnNames);
private JTable fileTable = new JTable(fileTableModel);
private JScrollPane scrollPane = new JScrollPane(fileTable);
private FillTable fillTableActionListener = new FillTable(fileTableModel);
private JPanel container = new JPanel();
private JCheckBox changeCol = new JCheckBox("ChangeCol");
public FillTableExample(){
selectButton.addActionListener(fillTableActionListener);
labelButtonPane.add(label);
labelButtonPane.add(selectButton);
changeCol.addActionListener(new DisplayPane());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setExtendedState(MAXIMIZED_BOTH);
this.setMinimumSize(new Dimension(400,400));
this.setResizable(true);
container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
container.add(labelButtonPane);
container.add(changeCol);
container.add(scrollPane);
this.setContentPane(container);
this.setVisible(true);
}
public class CustomTableModel extends AbstractTableModel {
private Object rowData[][];
private String[] columnNames;
public CustomTableModel(Object data[][], String[] titles){
rowData = data;
columnNames = titles;
}
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int column) {
return columnNames[column];
}
public int getRowCount() {
return rowData.length;
}
public Object getValueAt(int row, int column) {
return rowData[row][column];
}
public Class getColumnClass(int column) {
return this.rowData[0][column].getClass();
}
public int getColumnIndex(String columnName){
return Arrays.asList(columnNames).indexOf(columnName);
}
public void setValueAt(Object value, int row, int column) {
rowData[row][column] = value;
// fireTableDataChanged();
}
public boolean isCellEditable(int row, int column) {
if(column == 0 && columnNames[0].equals("Sample Name"))
return true;
else
return (column != 0);
}
}
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e){
final String[] tmpContent1 = {"", "", ""};
final String[] newColumnNames = {"File", "Name", "Extension"};
for (int i = 0; i < rowDataTable.length; i++)
rowDataTable[i] = tmpContent1;
fileTableModel = new CustomTableModel(rowDataTable, newColumnNames);
fileTable.setModel(fileTableModel);
fillTableActionListener.setModel(fileTableModel);
fileTableModel.fireTableStructureChanged();
fileTableModel.fireTableDataChanged();
}
}
class FillTable implements ActionListener {
private CustomTableModel model;
public FillTable(CustomTableModel model){
this.model = model;
}
public void actionPerformed(ActionEvent e){
final JFileChooser fc = new JFileChooser();
int returnVal;
fc.setMultiSelectionEnabled(true);
returnVal = fc.showOpenDialog(FillTableExample.this);
model.setValueAt("toto", 0, 0);
//I tried this, but you can see that toto is duplicated when clicking on cell
//((AbstractTableModel) fileTable.getModel()).fireTableCellUpdated(0, 0);
model.fireTableDataChanged();
}
public void setModel(CustomTableModel model){
this.model = model;
}
}
class FileEditor extends DefaultCellEditor {
public FileEditor(){
super(new JTextField());
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
JTextField editor = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
if(column == 0){
if(value != "toto")
editor.setText("");
else
editor.setText(value.toString());
}
return editor;
}
}
public static void main(String[] args) {
FillTableExample example = new FillTableExample();
example.setVisible(true);
}
}
[******************编辑]
我在构造函数中添加了命令"fileTable.getColumnModel().getColumn(0).setCellEditor(new FileEditor());"。同样的错误
这是使用 DefaultTableModel 的代码(同样的错误):
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
public class FillTableExample2 extends JFrame {
private JLabel label = new JLabel("File:");
private JButton selectButton = new JButton("Select");
private JPanel labelButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
private Object rowDataTable[][] = {{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""}};
private String[] columnNames = {"File", "Name"};
private DefaultTableModel fileTableModel = new DefaultTableModel(rowDataTable, columnNames);
private JTable fileTable = new JTable(fileTableModel);
private JScrollPane scrollPane = new JScrollPane(fileTable);
private FillTable fillTableActionListener = new FillTable(fileTableModel);
private JPanel container = new JPanel();
private JCheckBox changeCol = new JCheckBox("ChangeCol");
public FillTableExample2(){
selectButton.addActionListener(fillTableActionListener);
labelButtonPane.add(label);
labelButtonPane.add(selectButton);
changeCol.addActionListener(new DisplayPane());
fileTable.getColumnModel().getColumn(0).setCellEditor(new FileEditor());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setExtendedState(MAXIMIZED_BOTH);
this.setMinimumSize(new Dimension(400,400));
this.setResizable(true);
container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
container.add(labelButtonPane);
container.add(changeCol);
container.add(scrollPane);
this.setContentPane(container);
this.setVisible(true);
}
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e){
fileTableModel.addColumn("Extension");
}
}
class FillTable implements ActionListener {
private DefaultTableModel model;
public FillTable(DefaultTableModel model){
this.model = model;
}
public void actionPerformed(ActionEvent e){
final JFileChooser fc = new JFileChooser();
int returnVal;
fc.setMultiSelectionEnabled(true);
returnVal = fc.showOpenDialog(FillTableExample2.this);
model.setValueAt("toto", 0, 0);
}
}
class FileEditor extends DefaultCellEditor {
public FileEditor(){
super(new JTextField());
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
JTextField editor = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
if(value != "toto")
editor.setText("");
else
editor.setText(value.toString());
return editor;
}
}
public static void main(String[] args) {
FillTableExample example = new FillTableExample();
example.setVisible(true);
}
}
请找到固定的 class :
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e) {
final String[] newColumnNames = { "File", "Name", "Extension" };
for (int i = 0; i < rowDataTable.length; i++){
rowDataTable[i] =new String[] { "", "", "" }; // See below
}
fileTableModel = new CustomTableModel(rowDataTable, newColumnNames);
fileTable.setModel(fileTableModel);
fillTableActionListener.setModel(fileTableModel);
fileTableModel.fireTableStructureChanged();
fileTableModel.fireTableDataChanged();
}
}
该错误是由于对每一行使用相同的字符串数组造成的。
一个好的做法是从模型中触发事件。
非常感谢!问题是我在每一行中都复制了相同的 String[]。因此,修改一个字符串会在整个列中传播。声明一个新的 String[] 确保每行中有不同的内容。
在模型中放入一个 fireTableDataChanged() 并从 class 中删除 fileTableModel.fireTableStructureChanged() 和 fileTableModel.fireTableDataChanged() 就可以了。
完整的操作代码如下:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
public class FillTableExample extends JFrame {
private JLabel label = new JLabel("File:");
private JButton selectButton = new JButton("Select");
private JPanel labelButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
private Object rowDataTable[][] = {{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""}};
private String[] columnNames = {"File", "Name"};
private CustomTableModel fileTableModel = new CustomTableModel(rowDataTable, columnNames);
private JTable fileTable = new JTable(fileTableModel);
private JScrollPane scrollPane = new JScrollPane(fileTable);
private FillTable fillTableActionListener = new FillTable(fileTableModel);
private JPanel container = new JPanel();
private JCheckBox changeCol = new JCheckBox("ChangeCol");
public FillTableExample(){
selectButton.addActionListener(fillTableActionListener);
labelButtonPane.add(label);
labelButtonPane.add(selectButton);
changeCol.addActionListener(new DisplayPane());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setExtendedState(MAXIMIZED_BOTH);
this.setMinimumSize(new Dimension(400,400));
this.setResizable(true);
container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
container.add(labelButtonPane);
container.add(changeCol);
container.add(scrollPane);
this.setContentPane(container);
this.setVisible(true);
}
public class CustomTableModel extends AbstractTableModel {
private Object rowData[][];
private String[] columnNames;
public CustomTableModel(Object data[][], String[] titles){
rowData = data;
columnNames = titles;
}
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int column) {
return columnNames[column];
}
public int getRowCount() {
return rowData.length;
}
public Object getValueAt(int row, int column) {
return rowData[row][column];
}
public Class getColumnClass(int column) {
return this.rowData[0][column].getClass();
}
public int getColumnIndex(String columnName){
return Arrays.asList(columnNames).indexOf(columnName);
}
public void setValueAt(Object value, int row, int column) {
rowData[row][column] = value;
fireTableDataChanged();
}
public boolean isCellEditable(int row, int column) {
if(column == 0 && columnNames[0].equals("Sample Name"))
return true;
else
return (column != 0);
}
}
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e){
final String[] newColumnNames = {"File", "Name", "Extension"};
for (int i = 0; i < rowDataTable.length; i++)
rowDataTable[i] = new String[]{"", "", ""};
fileTableModel = new CustomTableModel(rowDataTable, newColumnNames);
fileTable.setModel(fileTableModel);
fillTableActionListener.setModel(fileTableModel);
}
}
class FillTable implements ActionListener {
private CustomTableModel model;
public FillTable(CustomTableModel model){
this.model = model;
}
public void actionPerformed(ActionEvent e){
final JFileChooser fc = new JFileChooser();
int returnVal;
fc.setMultiSelectionEnabled(true);
returnVal = fc.showOpenDialog(FillTableExample.this);
model.setValueAt("toto", 0, 0);
}
public void setModel(CustomTableModel model){
this.model = model;
}
}
public static void main(String[] args) {
FillTableExample example = new FillTableExample();
example.setVisible(true);
}
}
[**********编辑]
你是对的,使用 DefaultTableModel 代码更轻便和直接。这是更正后的示例 2:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
public class FillTableExample2 extends JFrame {
private JLabel label = new JLabel("File:");
private JButton selectButton = new JButton("Select");
private JPanel labelButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
private Object rowDataTable[][] = {{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""}};
private String[] columnNames = {"File", "Name"};
private DefaultTableModel fileTableModel = new DefaultTableModel(rowDataTable, columnNames);
private JTable fileTable = new JTable(fileTableModel);
private JScrollPane scrollPane = new JScrollPane(fileTable);
private FillTable fillTableActionListener = new FillTable(fileTableModel);
private JPanel container = new JPanel();
private JCheckBox changeCol = new JCheckBox("ChangeCol");
public FillTableExample2(){
selectButton.addActionListener(fillTableActionListener);
labelButtonPane.add(label);
labelButtonPane.add(selectButton);
changeCol.addActionListener(new DisplayPane());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setExtendedState(MAXIMIZED_BOTH);
this.setMinimumSize(new Dimension(400,400));
this.setResizable(true);
container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
container.add(labelButtonPane);
container.add(changeCol);
container.add(scrollPane);
this.setContentPane(container);
this.setVisible(true);
}
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e){
fileTableModel.addColumn("Extension");
}
}
class FillTable implements ActionListener {
private DefaultTableModel model;
public FillTable(DefaultTableModel model){
this.model = model;
}
public void actionPerformed(ActionEvent e){
final JFileChooser fc = new JFileChooser();
int returnVal;
fc.setMultiSelectionEnabled(true);
returnVal = fc.showOpenDialog(FillTableExample2.this);
model.setValueAt("toto", 0, 0);
}
}
public static void main(String[] args) {
FillTableExample2 example = new FillTableExample2();
example.setVisible(true);
}
}
我又在和 JTable 纠缠了,我很卡。
问题是:
- 我有一个 select 文件路径的按钮来填充我的 JTable 的第一列:这工作正常。
- 单击一个复选框,我更改 jtable 的结构以添加或删除列:这工作正常。
- 当我再次尝试用文件路径填充新 table 时,只有最后一个 selected 被复制到列的每一行中。
我发现很多帖子都有类似的问题,但无法解决(尝试 cellRenderer、cellEditor、修改模型等)。下面我尽量把代码精简到最简单。我尝试了很多不同的东西,但我真的不明白发生了什么事的逻辑(我完整地阅读了文档,但显然我遗漏了一些东西)。
我也试过用DefaultTableModel做一个版本,但问题似乎是独立的。此外,我想保留 AbstractTableModel 因为其他 类 使用它。我认为模型中出现了问题,但我不知道是什么(在模型中也尝试了不同的火***)。
如果您看到错误并能解释其背后的逻辑,将不胜感激。
非常感谢。这是我认为不言自明的代码:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
public class FillTableExample extends JFrame {
private JLabel label = new JLabel("File:");
private JButton selectButton = new JButton("Select");
private JPanel labelButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
private Object rowDataTable[][] = {{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""}};
private String[] columnNames = {"File", "Name"};
private CustomTableModel fileTableModel = new CustomTableModel(rowDataTable, columnNames);
private JTable fileTable = new JTable(fileTableModel);
private JScrollPane scrollPane = new JScrollPane(fileTable);
private FillTable fillTableActionListener = new FillTable(fileTableModel);
private JPanel container = new JPanel();
private JCheckBox changeCol = new JCheckBox("ChangeCol");
public FillTableExample(){
selectButton.addActionListener(fillTableActionListener);
labelButtonPane.add(label);
labelButtonPane.add(selectButton);
changeCol.addActionListener(new DisplayPane());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setExtendedState(MAXIMIZED_BOTH);
this.setMinimumSize(new Dimension(400,400));
this.setResizable(true);
container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
container.add(labelButtonPane);
container.add(changeCol);
container.add(scrollPane);
this.setContentPane(container);
this.setVisible(true);
}
public class CustomTableModel extends AbstractTableModel {
private Object rowData[][];
private String[] columnNames;
public CustomTableModel(Object data[][], String[] titles){
rowData = data;
columnNames = titles;
}
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int column) {
return columnNames[column];
}
public int getRowCount() {
return rowData.length;
}
public Object getValueAt(int row, int column) {
return rowData[row][column];
}
public Class getColumnClass(int column) {
return this.rowData[0][column].getClass();
}
public int getColumnIndex(String columnName){
return Arrays.asList(columnNames).indexOf(columnName);
}
public void setValueAt(Object value, int row, int column) {
rowData[row][column] = value;
// fireTableDataChanged();
}
public boolean isCellEditable(int row, int column) {
if(column == 0 && columnNames[0].equals("Sample Name"))
return true;
else
return (column != 0);
}
}
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e){
final String[] tmpContent1 = {"", "", ""};
final String[] newColumnNames = {"File", "Name", "Extension"};
for (int i = 0; i < rowDataTable.length; i++)
rowDataTable[i] = tmpContent1;
fileTableModel = new CustomTableModel(rowDataTable, newColumnNames);
fileTable.setModel(fileTableModel);
fillTableActionListener.setModel(fileTableModel);
fileTableModel.fireTableStructureChanged();
fileTableModel.fireTableDataChanged();
}
}
class FillTable implements ActionListener {
private CustomTableModel model;
public FillTable(CustomTableModel model){
this.model = model;
}
public void actionPerformed(ActionEvent e){
final JFileChooser fc = new JFileChooser();
int returnVal;
fc.setMultiSelectionEnabled(true);
returnVal = fc.showOpenDialog(FillTableExample.this);
model.setValueAt("toto", 0, 0);
//I tried this, but you can see that toto is duplicated when clicking on cell
//((AbstractTableModel) fileTable.getModel()).fireTableCellUpdated(0, 0);
model.fireTableDataChanged();
}
public void setModel(CustomTableModel model){
this.model = model;
}
}
class FileEditor extends DefaultCellEditor {
public FileEditor(){
super(new JTextField());
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
JTextField editor = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
if(column == 0){
if(value != "toto")
editor.setText("");
else
editor.setText(value.toString());
}
return editor;
}
}
public static void main(String[] args) {
FillTableExample example = new FillTableExample();
example.setVisible(true);
}
}
[******************编辑]
我在构造函数中添加了命令"fileTable.getColumnModel().getColumn(0).setCellEditor(new FileEditor());"。同样的错误
这是使用 DefaultTableModel 的代码(同样的错误):
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
public class FillTableExample2 extends JFrame {
private JLabel label = new JLabel("File:");
private JButton selectButton = new JButton("Select");
private JPanel labelButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
private Object rowDataTable[][] = {{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""}};
private String[] columnNames = {"File", "Name"};
private DefaultTableModel fileTableModel = new DefaultTableModel(rowDataTable, columnNames);
private JTable fileTable = new JTable(fileTableModel);
private JScrollPane scrollPane = new JScrollPane(fileTable);
private FillTable fillTableActionListener = new FillTable(fileTableModel);
private JPanel container = new JPanel();
private JCheckBox changeCol = new JCheckBox("ChangeCol");
public FillTableExample2(){
selectButton.addActionListener(fillTableActionListener);
labelButtonPane.add(label);
labelButtonPane.add(selectButton);
changeCol.addActionListener(new DisplayPane());
fileTable.getColumnModel().getColumn(0).setCellEditor(new FileEditor());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setExtendedState(MAXIMIZED_BOTH);
this.setMinimumSize(new Dimension(400,400));
this.setResizable(true);
container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
container.add(labelButtonPane);
container.add(changeCol);
container.add(scrollPane);
this.setContentPane(container);
this.setVisible(true);
}
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e){
fileTableModel.addColumn("Extension");
}
}
class FillTable implements ActionListener {
private DefaultTableModel model;
public FillTable(DefaultTableModel model){
this.model = model;
}
public void actionPerformed(ActionEvent e){
final JFileChooser fc = new JFileChooser();
int returnVal;
fc.setMultiSelectionEnabled(true);
returnVal = fc.showOpenDialog(FillTableExample2.this);
model.setValueAt("toto", 0, 0);
}
}
class FileEditor extends DefaultCellEditor {
public FileEditor(){
super(new JTextField());
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
JTextField editor = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
if(value != "toto")
editor.setText("");
else
editor.setText(value.toString());
return editor;
}
}
public static void main(String[] args) {
FillTableExample example = new FillTableExample();
example.setVisible(true);
}
}
请找到固定的 class :
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e) {
final String[] newColumnNames = { "File", "Name", "Extension" };
for (int i = 0; i < rowDataTable.length; i++){
rowDataTable[i] =new String[] { "", "", "" }; // See below
}
fileTableModel = new CustomTableModel(rowDataTable, newColumnNames);
fileTable.setModel(fileTableModel);
fillTableActionListener.setModel(fileTableModel);
fileTableModel.fireTableStructureChanged();
fileTableModel.fireTableDataChanged();
}
}
该错误是由于对每一行使用相同的字符串数组造成的。 一个好的做法是从模型中触发事件。
非常感谢!问题是我在每一行中都复制了相同的 String[]。因此,修改一个字符串会在整个列中传播。声明一个新的 String[] 确保每行中有不同的内容。
在模型中放入一个 fireTableDataChanged() 并从 class 中删除 fileTableModel.fireTableStructureChanged() 和 fileTableModel.fireTableDataChanged() 就可以了。
完整的操作代码如下:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
public class FillTableExample extends JFrame {
private JLabel label = new JLabel("File:");
private JButton selectButton = new JButton("Select");
private JPanel labelButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
private Object rowDataTable[][] = {{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""}};
private String[] columnNames = {"File", "Name"};
private CustomTableModel fileTableModel = new CustomTableModel(rowDataTable, columnNames);
private JTable fileTable = new JTable(fileTableModel);
private JScrollPane scrollPane = new JScrollPane(fileTable);
private FillTable fillTableActionListener = new FillTable(fileTableModel);
private JPanel container = new JPanel();
private JCheckBox changeCol = new JCheckBox("ChangeCol");
public FillTableExample(){
selectButton.addActionListener(fillTableActionListener);
labelButtonPane.add(label);
labelButtonPane.add(selectButton);
changeCol.addActionListener(new DisplayPane());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setExtendedState(MAXIMIZED_BOTH);
this.setMinimumSize(new Dimension(400,400));
this.setResizable(true);
container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
container.add(labelButtonPane);
container.add(changeCol);
container.add(scrollPane);
this.setContentPane(container);
this.setVisible(true);
}
public class CustomTableModel extends AbstractTableModel {
private Object rowData[][];
private String[] columnNames;
public CustomTableModel(Object data[][], String[] titles){
rowData = data;
columnNames = titles;
}
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int column) {
return columnNames[column];
}
public int getRowCount() {
return rowData.length;
}
public Object getValueAt(int row, int column) {
return rowData[row][column];
}
public Class getColumnClass(int column) {
return this.rowData[0][column].getClass();
}
public int getColumnIndex(String columnName){
return Arrays.asList(columnNames).indexOf(columnName);
}
public void setValueAt(Object value, int row, int column) {
rowData[row][column] = value;
fireTableDataChanged();
}
public boolean isCellEditable(int row, int column) {
if(column == 0 && columnNames[0].equals("Sample Name"))
return true;
else
return (column != 0);
}
}
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e){
final String[] newColumnNames = {"File", "Name", "Extension"};
for (int i = 0; i < rowDataTable.length; i++)
rowDataTable[i] = new String[]{"", "", ""};
fileTableModel = new CustomTableModel(rowDataTable, newColumnNames);
fileTable.setModel(fileTableModel);
fillTableActionListener.setModel(fileTableModel);
}
}
class FillTable implements ActionListener {
private CustomTableModel model;
public FillTable(CustomTableModel model){
this.model = model;
}
public void actionPerformed(ActionEvent e){
final JFileChooser fc = new JFileChooser();
int returnVal;
fc.setMultiSelectionEnabled(true);
returnVal = fc.showOpenDialog(FillTableExample.this);
model.setValueAt("toto", 0, 0);
}
public void setModel(CustomTableModel model){
this.model = model;
}
}
public static void main(String[] args) {
FillTableExample example = new FillTableExample();
example.setVisible(true);
}
}
[**********编辑]
你是对的,使用 DefaultTableModel 代码更轻便和直接。这是更正后的示例 2:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
public class FillTableExample2 extends JFrame {
private JLabel label = new JLabel("File:");
private JButton selectButton = new JButton("Select");
private JPanel labelButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
private Object rowDataTable[][] = {{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""},
{"", ""}, {"", ""}, {"", ""}, {"", ""}};
private String[] columnNames = {"File", "Name"};
private DefaultTableModel fileTableModel = new DefaultTableModel(rowDataTable, columnNames);
private JTable fileTable = new JTable(fileTableModel);
private JScrollPane scrollPane = new JScrollPane(fileTable);
private FillTable fillTableActionListener = new FillTable(fileTableModel);
private JPanel container = new JPanel();
private JCheckBox changeCol = new JCheckBox("ChangeCol");
public FillTableExample2(){
selectButton.addActionListener(fillTableActionListener);
labelButtonPane.add(label);
labelButtonPane.add(selectButton);
changeCol.addActionListener(new DisplayPane());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setExtendedState(MAXIMIZED_BOTH);
this.setMinimumSize(new Dimension(400,400));
this.setResizable(true);
container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
container.add(labelButtonPane);
container.add(changeCol);
container.add(scrollPane);
this.setContentPane(container);
this.setVisible(true);
}
class DisplayPane implements ActionListener {
public void actionPerformed(ActionEvent e){
fileTableModel.addColumn("Extension");
}
}
class FillTable implements ActionListener {
private DefaultTableModel model;
public FillTable(DefaultTableModel model){
this.model = model;
}
public void actionPerformed(ActionEvent e){
final JFileChooser fc = new JFileChooser();
int returnVal;
fc.setMultiSelectionEnabled(true);
returnVal = fc.showOpenDialog(FillTableExample2.this);
model.setValueAt("toto", 0, 0);
}
}
public static void main(String[] args) {
FillTableExample2 example = new FillTableExample2();
example.setVisible(true);
}
}