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];
}
}
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);
}
}
I need some help with getValue method
Im reading from a file and storing the values in a
public List<Object[]> students;
Now I want to add all of this values to my JTable
#Override
public Object getValueAt(int row, int col) {
//return data[row][col];
// Here I have to get data from students
}
Usually from a lot of example I saw that they use Object[][] data for doing this kind of thing
this could be something like this
//return data[row][col];
but since I read from a file I want List<Object[]> students;
Any Idea how to implement this in getValueAt method?
my solution will be this
#Override
public Object getValueAt(int row, int col) {
//return data[row][col];
for(Object[] j: students)
{
return j[col];
}
return null;
}
but this will only take the first object and will assign to all rows in my JTable
how about:
#Override
public Object getValueAt(int row, int col) {
return students.get(row)[col];
}
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);
}
...
}
I have a vector with HashMap elements.
I want to put it in a table and every HashTable value must be in column with HashTable key column-title.
So elements with key "key1" must appear on table column with name "key1".
The problem is when I try to add/remove columns of table with setHash() function.
I pass a String[] with more/fewer elements and when this function run the fireTableStructureChanged() java throws like crazy.
I don't understand where is the problem. Can you help me please?
The implementation of Table Model is here:
public class ResizableTableModel extends AbstractTableModel {
protected DataSource src;
protected String[] hash;
//......................
public void setHash(String[] hash) {
this.hash = hash;
fireTableStructureChanged(); // THROWS!
}
public ArrayList getData() { return src.getData(); }
public int getColumnCount() { return hash.length; }
public int getRowCount() { return getData() == null ? 0 : getData().size(); }
public String getColumnName(int col) { return hash[col]; }
public boolean isCellEditable(int row, int col) { return true; }
public Object getValueAt(int row, int col) {
try {
return ((HashMap) getData().get(row)).get(hash[col]);
} catch (Exception e) {
return null;
}
}
public void setValueAt(Object obj, int row, int col) {
try {
//...................
} catch (Exception e) {}
fireTableDataChanged();
}
}
don't to remove Columns from XxxTableModel,
remove Column from JTables view only, data are still stored and accesible in XxxTableModel