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);
}
...
}
Related
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);
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 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
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.