I am struggling again with JTable and I am very stuck.
The problem is:
I have found many posts with a similar problem but could not sort things out (Try cellRenderer, cellEditor, modify the model and so on). Below I tried to reduce the code to the minimum to make it simple. I have tried many different things but I really do not understand the logic of what is going on (I read the doc entirely, but obviously I am missing something).
I have also tried to do a version with DefaultTableModel, but the problem seems to be independent. Moreover I would like to keep AbstractTableModel because of other classes using it. I think that something is going wrong in the model but I do not know what (tried also different fire*** in the model).
If you see the error and can explain the logic behind it, it would be much appreciated.
Thanks a lot. Here is the code that is, I think, self-explaining:
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);
}
}
[****************EDIT]
I have added the command "fileTable.getColumnModel().getColumn(0).setCellEditor(new FileEditor());" in the constructor. Same error
Here is the code using DefaultTableModel (same error):
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);
}
}
Please find the fixed 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();
}
}
The error was caused by the usage of the same String array for every rows. A good practice is to fire event from the model.