Can't construct a JTable with int[][] and String[] arguments - java

The constructor JTable is giving me an error that says:
"The constructor JTable(int[][], String[]) is undefined"
although it has a constructor JTable(Object[][], Object[]) (Calcul.apartements is of the type int[][])
String[] colonnes = {"Appartements", "Prix Milion de Cts", "Tempd duTrajet/C.v (en min)", "Superficie (en m2)", "Etage"};
table = new JTable(Calcul.appartements, colonnes);

You have two choices:
alter your Calcul.appartements data to be Object[][] or Integer[][] (as mentioned by #MadProgrammer in the comments)
Implement your own table model.
Implementing the table model might be as simple as:
TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() { return colonnes.length; }
public String getColumnName(int col) { return colonnes[col]; }
public int getRowCount() { return Calcul.appartements.length; }
public Object getValueAt(int row, int col) { Calcul.appartements[row][col]; }
};
JTable table = new JTable(dataModel);

Related

how to arrange jtable according to a specific column [duplicate]

This question already has answers here:
Sorting rows by columns in JTable
(2 answers)
How to sort JTable in shortest way?
(2 answers)
Closed 5 years ago.
I have a program that reads a CSV file (it's a table) using BufferedReader which stores it in ArrayList.
The column I want to sort according to is an integer value and i want to do it in ascending order. The column I want to use is column 2. I want the column to be sorted as soon as I open the jtable. I have tried using TableRowSorter but I want the table to automatically sort. Is there any other way of doing it. I have used AbstractTableModel maybe I can input a code there.
Class MyModel extends AbstractTableModel {
private final String[] columnNames = { "Studentname" "Age" "Id"}
private Class[] columnClass = { String.class, Integer.class, Integer.class };
private ArrayList<String[]> Data = new ArrayList<String[]>();
public void AddCSVData(ArrayList<String[]> DataIn) {
this.Data = DataIn;
this.fireTableDataChanged();
}
#Override
public int getColumnCount() {
return columnNames.length;// length;
}
#Override
public int getRowCount() {
return Data.size();
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
public void setValueAt(Object aValue, int row, int col) {
Data.get(row)[col] = (String) aValue;
}
#Override
public Object getValueAt(int row, int col) {
return Data.get(row)[col];
}
}

ArrayOutOfBoundsException when removing Objects from a JTable

I'm a complete newbie to Java. I've only been learning it for half a year now. Right now I am working on a Project for school and I've hit a complete wall:
I am basically making a Program to manage your own Books. I have a class that is "Books", which holds the data for the book objects. Then there's the class "Library" which holds an ArrayList of Books. For the TableModel, I am using a class ("LibraryTableModel") that extends AbstractTableModel. I then have a GUI class wich displays the table.
The table actually works, but there are two instances where the program crashes:
When I add a Book to an empty Library, the table doesn't update. However, the Book IS added when I start the program anew (I save the Library class as a .ser file).
Then the instance which I am asking about: I have a button that removes Books from the table. the Button itself works fine, but when I remove a book, the program throws an ArrayOutOfBoundsException. When I create the table anew, it updates and the book is removed. What is the problem here, why does the program crash instead of update the table?
Code for TableModel:
public class LibraryTableModel extends AbstractTableModel
{
private String[] columnNames = {"Titel", "Autor", "Status", "Genre", "Verlag", "Seitenzahl", "ISBN", "Sprache", "Bewertung"};
private Object[][] data = {};
ArrayList<Book> lib;
public LibraryTableModel(Library l)
{
//This Method returns the ArrayList in the Library class
lib = l.getList();
int libSize = lib.size();
data = new Object[bib.size()][];
for (Book b : lib)
{
int index = bib.indexOf(b);
//(...)
//CODE HERE gets all the data that is supposed to be displayed
//from each book in the ArrayList
Object[] oA = {tit, aut, sta, gen, ver, sei, isb, spr, bew};
data[index] = oA;
}
}
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];
//When I try to remove a Book, the ArrayOutOfBounds Exception comes from here
}
public Class getColumnClass(int c)
{
return getValueAt(0, c).getClass();
}
public void setValueAt(Object value, int row, int col)
{
data[row][col] = value;
fireTableCellUpdated(row, col);
}
public void removeRow(int row)
{
lib.remove(row);
fireTableRowsDeleted(row, row);
}
Code in the GUI class that is revolving around the table and the tablemodel:
public class GUI implements ActionListener
{
JTable table;
LibraryTableModel model;
TableRowSorter<BibliothekTableModel> sorter;
Library lib;
JMenuItem deleteBook;
(...) The Library is loaded through the .ser file
public void showTable() //This method is envoked in the GUI constructor through pressing a button
{
model = new LibraryTableModel(lib);
table.setModel(model);
deleteBook.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
model.removeRow(row);
//Code that saves the library at this point
table.setModel(new LibraryTableModel(lib));
}
});
popupMenu.add(deleteBook);
table.setComponentPopupMenu(popupMenu);
sorter = new TableRowSorter<BibliothekTableModel>(model);
table.setRowSorter(sorter);
JScrollPane scrollTable = new JScrollPane(table);
//Next is code, that adds this ScrollPane to my Frame
}
When I add a Book to an empty Library, the table doesn't update. However, the Book IS added when I start the program anew (I save the Library class as a .ser file).
There is no information provided which demonstrates how this works...and what's a .ser file?
Then the instance which I am asking about: I have a button that
removes Books from the table. the Button itself works fine, but when I
remove a book, the program throws an ArrayOutOfBoundsException. When I
create the table anew, it updates and the book is removed. What is the
problem here, why does the program crash instead of update the table?
There are two issues...
First, because you are using a RowSorter on the table, the visual row index returned by JTable#getSelectedRow and the physical row index in the model won't be the same, you need to use JTable#convertRowIndexToModel
int row = table.getSelectedRow();
row = table.convertRowIndexToModel(row);
model.removeRow(row);
//Code that saves the library at this point
Second, you're removing the book from the lib, but not updating the internal cache...
public void removeRow(int row)
{
lib.remove(row);
fireTableRowsDeleted(row, row);
}
The model isn't using the lib as it's source for the data, but is using the data array, which you have not updated.
While you could simply rebuild the data array, a better solution would be to get rid of it and use the lib directly, for example...
public class LibraryTableModel extends AbstractTableModel {
private String[] columnNames = {"Titel", "Autor", "Status", "Genre", "Verlag", "Seitenzahl", "ISBN", "Sprache", "Bewertung"};
private Object[][] data = {};
private Library lib;
public LibraryTableModel(Library l) {
lib = l;
}
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return lib.getList().size();
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
Book book = lib.getList().get(row);
Object value = null;
switch (col) {
case 0:
value = ...;
break;
case 1:
value = ...;
break;
case 2:
value = ...;
break;
case 3:
value = ...;
break;
case 4:
value = ...;
break;
case 5:
value = ...;
break;
case 6:
value = ...;
break;
case 7:
value = ...;
break;
case 8:
value = ...;
break;
}
return value;
//When I try to remove a Book, the ArrayOutOfBounds Exception comes from here
}
public Class getColumnClass(int c) {
// Don't do this, know the actualy value and return it
// Otherwise you could end up with a NullPointerException
return getValueAt(0, c).getClass();
}
public void setValueAt(Object value, int row, int col) {
// Use a simular technquie to getValueAt to extract the Book for the give
// row and update the Book's attributes
fireTableCellUpdated(row, col);
}
public void removeRow(int row) {
lib.remove(row);
fireTableRowsDeleted(row, row);
}
}

Updating ArrayList<Object[]> within model is producing a compilation error

Modified a sample i found that uses a model.
Originally the sample would only add a new record.
The code was modified to allow editing of the fields and included the setValueAt() call
in order to maintain any changes.
The data is stored within an ArrayList of an Object array and this is producing errors when trying to update the ArrayList.
When using:
al.set(row, value);
It produces the error :
TableWithModel.java:66: error: no suitable method found for set(int,Object)
al.set(row, value);
^
method ArrayList.set(int,Object[]) is not applicable
(actual argument Object cannot be converted to Object[] by method invocation conversion)
1 error
Tried doing a variety of different syntax but just get different errors.
Something obvious is being overlooked but not sure what.
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableWithModel extends JFrame {
MyModel model;
TableWithModel(Object[][] obj, String[] header) {
super("Static JTable example");
JPanel panel = new JPanel(new BorderLayout());
model = new MyModel(obj, header);
JTable table = new JTable(model);
panel.add(new JScrollPane(table));
add(panel); // adding panel to frame
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
pack();
}
public static void main(String[] args) {
String[][] rowAndColumn = {
{"Row1", "Column2"},
{"Row2", "Column2"},
{"Row3", "Column2"},
{"Row4", "Column2"}
};
String[] header = {"Column1", "Column2"};
TableWithModel twm = new TableWithModel(rowAndColumn, header);
}
class MyModel extends AbstractTableModel {
ArrayList<Object[]> al;
String[] header;
MyModel(Object[][] obj, String[] header) {
this.header = header;
al = new ArrayList<Object[]>();
for(int i = 0; i < obj.length; ++i)
al.add(obj[i]);
}
public int getRowCount() {
return al.size();
}
public int getColumnCount() {
return header.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return al.get(rowIndex)[columnIndex];
}
public String getColumnName(int index) {
return header[index];
}
public boolean isCellEditable(int row, int col)
{ return true; }
public void setValueAt(Object value, int row, int col) {
al.set(row, value);
fireTableCellUpdated(row, col);
}
}
}
The ArrayList variable al holds arrays of objects. To update the object array element at column col stored at index row in the ArrayList, you need to use the following:
public void setValueAt(Object value, int row, int col) {
al.get(row)[col] = value;
fireTableCellUpdated(row, col);
}
al.get(row)[col] = value; is a shorthand for the following:
Object[] data = al.get(row);
data[col] = value;
This is similar to what's already implemented in the getValueAt method except that you're setting the array element instead of retrieving it.
The reason why al.set(row, value); does not compile is that the set method expects the second argument to be an Object[] array, and not an Object, since that's what the ArrayList holds.
Thanks for the reply.
Ran a quick test and it works.
What is a bit strange is call "get" instead of "set".
Shortly after posting I was able to find a solution using "set"
Object[] data = al.get(row);
data[col] = value;
al.set(row, data);
It makes sense using the set but what is it that makes it work in your example using "get"?

JTable, refreshing rowData vector in static context

i've declared a JTable (inside a class extended JPanel constructor) such as
data_table = new JTable(info, header) {
#Override
public boolean isCellEditable(int row, int column) {
//disable table editing
return false;
}
};
where info and column are declared
static String[][] info = new String[row][cols];
static String[] header = {"h1", "h2", "h3"};
Now i need to update, when some events occours, the table content by invoke a static method. How can i do it?
i don't have a tableModel, i've a matrix of string
All tables use a TableModel. When you create the table the matrix of Strings is used by the TableModel.
To update your data you do something like:
table.setValueAt(...);
This will cause the model to be updated and the model will tell the table to repaint itself.
Read the Swing tutorial on How to Use Tables for more information about tables.
Also, you should NOT be using static variables or method. If you are then you program is poorly designed. Again read the tutorial for a better example of how to structure your code.
If you want to notify your JTable about changes of your data, call a method on your tablemodel that will update the data and call fireTableDataChanged()
Its is a good practice to use a JTableModel to maintain your data inside the JTable.
http://docs.oracle.com/javase/tutorial/uiswing/components/table.html
And that is your tablemodel that will fire the fireTableDataChanged() when value will change.
class MyTableModel extends AbstractTableModel {
private String[] columnNames = ...//same as before...
private Object[][] data = ...//same as before...
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];
}
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) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
...
}

Delete a row from JTable

I have a table model. I want to delete a row from a table. I am not able to find the model.removeRow method. Can someone tell he how to remove a row? Below is the code for the model.
class TableModel extends AbstractTableModel {
private Object[][] data;
private String[] columnNames;
public TableModel(Object[][] data) {
this.data = data;
columnNames=new String[1];
columnNames[0]="Data";
}
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return columnNames.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
public Class getColumnClass(int c) {
return String.class;
}
public boolean isCellEditable(int rowIndes, int columnIndex) {
return false;
}
public String getColumnName(int index) {
return columnNames[index];
}
public void setValueAt(Object value, int rowIndex, int columnIndex) {
data[rowIndex][columnIndex] = value;
fireTableCellUpdated(rowIndex, columnIndex);
}
}
Use DefaultTableModel. It has public void removeRow(int row) method.
you must be missing something that is obvious in the default model, maybe you're mot overriding properly if you're doing your own and you might thing it's missing :
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
// Create some data
model.addColumn("Col1");
model.addRow(new Object[]{"r1"});
model.addRow(new Object[]{"r2"});
model.addRow(new Object[]{"r3"});
// Remove the first row
model.removeRow(0);
// Remove the last row
model.removeRow(model.getRowCount()-1);
DefaultTableModel is one solution. But if yo still want to use abstrac table model, this is how you do.
This is the new model definition.
class TableModel extends AbstractTableModel {
private Object[][] data;
private String[] columnNames;
public TableModel(Object[][] data) {
this.data = data;
columnNames=new String[1];
columnNames[0]="Data";
}
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return columnNames.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex][columnIndex];
}
public Class getColumnClass(int c) {
return String.class;
}
public boolean isCellEditable(int rowIndes, int columnIndex) {
return false;
}
public String getColumnName(int index) {
return columnNames[index];
}
public void removeRow(int row)
{
Object [][]newData=new Object[data.length-1][data[0].length];
for(int i=0;i<newData.length;i++){
for(int j=0;j<data[0].length;j++){
newData[i][j]=data[i+1][j];
}
}
data=new Object[newData.length][columnNames.length];
data=newData;
fireTableRowsDeleted(row, row);
}
public void setValueAt(Object value, int rowIndex, int columnIndex) {
data[rowIndex][columnIndex] = value;
fireTableCellUpdated(rowIndex, columnIndex);
}
}
You first need to remove the row data from the data object. and then remove the row.
Kaushik, if you really want to make your own implementation of the TableModel interface and deal with the storage of rows manually (as you obviously do by using Object[][] data), then you must implement the removeRow() method because abstract table model does not "know" how to do it. removeRow() will have to fireTableRowsDeleted() at the end...
A good alternative is to refactor your class and make it extend the DefaultTableModel.
Another suggestion - since table model changes a lot, a dynamic array may be a bad choice for storage because you must either reallocate space every time you add a row (bad), or you preallocate enough space for certain number of rows, then whenever there is no enough space you allocate new Object[][] with some extra space (for next N rows). Typically people allocate enough space for 2^n rows during the reallocation process.

Categories