Java 填充文件的JTable在模型修改后重复值(AbstractTableModel)
我又在为JTable苦苦挣扎,我被卡住了 问题是:Java 填充文件的JTable在模型修改后重复值(AbstractTableModel),java,swing,jtable,jbutton,abstracttablemodel,Java,Swing,Jtable,Jbutton,Abstracttablemodel,我又在为JTable苦苦挣扎,我被卡住了 问题是: 我有一个按钮来选择文件路径以填充JTable的第一列:这很好 单击一个复选框,我将更改jtable的结构以添加或删除列:这很好 当我再次尝试用文件路径填充新表时,在列的每一行中只复制最后一个选定的路径 我发现很多帖子都有类似的问题,但无法解决(试试cellRenderer、cellEditor、修改模型等等)。下面,我试图将代码减少到最低限度,使其变得简单。我尝试了很多不同的事情,但我真的不明白发生了什么事情的逻辑(我完全阅读了文档,但显然
- 我有一个按钮来选择文件路径以填充JTable的第一列:这很好
- 单击一个复选框,我将更改jtable的结构以添加或删除列:这很好
- 当我再次尝试用文件路径填充新表时,在列的每一行中只复制最后一个选定的路径
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);
}
}
请查找固定类别:
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();
}
}
class DisplayPane实现ActionListener{
已执行的公共无效操作(操作事件e){
最终字符串[]newColumnNames={“文件”、“名称”、“扩展名”};
对于(int i=0;i
该错误是由于对每行使用相同的字符串数组造成的。
一个好的做法是从模型中触发事件。非常感谢!问题是我在每行复制相同的字符串[]。因此,修改一个字符串在整个列中传播。声明新字符串[]可确保每行中都有不同的内容 将fireTableDataChanged()放在模型中,然后从类中删除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);
}
}
我认为您没有理由扩展AbstractTableModel。您可以使用DefaultTableModel,只需在适当的地方重写方法,比如isCellEditable(…)方法
还尝试了在模型中使用不同的fire***)。
-实际上,您没有在模型中使用它,这是使用DefaultTableModel的另一个原因,因为它已经为您提供了这一功能。您不应该在TableModel之外调用这些方法。对于自定义编辑器,您不应该检查列。编辑器只应添加到第一列,因此不需要进行检查。所有其他列都将使用默认编辑器。谢谢。我已经用DefaultTableModel做了一个代码(见编辑)并删除了fire***。同样的问题。我已经用DefaultTableModel编写了一个代码(请参见编辑)
-不知道如何测试它,因为main()方法仍然调用第一个示例当我再次尝试用文件路径填充新表时,在列的每一行中只复制最后一个选定的路径。
-不知道这意味着什么,“选择”按钮除了显示文件选择器外,什么都不做。我不知道如何测试代码。文件路径上的注释对我的初始程序有效。我对它进行了简化,使示例变得简单。问题在于您没有按照所述创建新字符串。正如我已经建议的,您不需要扩展AbstractTableModel。您不应该在setValueAt()方法中调用fireTableDataChanged(…)。有一种更合适的fireXXX方法可供使用。这一切都在DefaultTableModel中正确完成。只需使用DefaultTableModel来实现这样的基本功能。谢谢,你说得对。我已经用DefaultTableModel更新了答案(请参见编辑)。感谢camickr5和blueEOS。+不需要FileEditor类。如果您错了,必须从事件调度线程调用fireXXX。。。该错误是由于对每行使用相同的字符串数组造成的。谢谢你的否决票!我打赌你没有运行程序来解决问题。fireXXX必须从事件调度线程调用
-正确。但是,TableModel(不是应用程序代码)负责调用fireXXX(…)方法。对TableModel的更新必须在EDT中完成该错误是由于对每行使用相同的字符串数组造成的
-正确,但这不是否决票的目的。fireXXX()代码是错误的!另外,当你回答一个问题时,你应该陈述问题和解决方案,而不是仅仅发布几行随机的代码让每个人猜测问题是什么。
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);
}
}
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);
}
}