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
Related
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 have got JTable with datas from DataBase. Once the table is filled but somotimes (totally random) not. Connection with DB is correct. I haven't got any idea why in one situation table is filled and in other not. there is absolutely no rule.
Model class:
public class MaterialModel extends AbstractTableModel
{
public List<Material> materials = new ArrayList<Material>();
String[] columns = {"ID_Material", "Nazwa"};
public int getRowCount() {
return this.materials.size();
}
public int getColumnCount() {
return columns.length;
}
public String getColumnName(int col){
return columns[col];
}
public Object getValueAt(int rowIndex, int columnIndex) {
Material material = materials.get(rowIndex);
switch (columnIndex)
{
case 0: return material.id;
case 1: return material.name;
}
return null;
}
public void setListMaterials(List<Material> listMaterials){
this.materials = listMaterials;
}
public void reset(){
this.materials.clear();
}
}
Form class:
public class Form extends JFrame{
private JTable materialTable;
MaterialDAO materialDAO;
public MaterialModel materialModel;
public Form() throws SQLException {
super("Magazyn");
setContentPane(mainPane);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500,500);
this.initComponets();
materialDAO = new MaterialDaoImpl();
materialTable.setModel(new MaterialModel());
this.fillTable();
}
public void fillTable() throws SQLException {
this.materialTable.repaint();
materialModel = (MaterialModel) this.materialTable.getModel();
materialModel.reset();
materialModel.setListMaterials(materialDAO.getAllMaterials());
}
}
Thank you a lot for your help.
As i see there is no SQL query, check if you are executing a sql query, i don't know if you are using Hibernate or something other, try to put the part of executing sql query, by this way we can see the error you did.
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've figured out why my arraylist was always returning a size of 0 but I can't fix the problem. I have a custom model with an "addHuman(Human h) method that is intended to add to an array. Only problem is that it doesn't. Now, if I were to use the regular method, say model.add(index, object o) it would actually work and increment the size of my arraylist but doesn't display on my jtable. My question is how can I make this work for my custom addHuman method? Any help much appreciated!
and the following is the main class that uses that method. When I click on the button to addIndividual, it's supposed to add the human to my HumanListModel:
addIndividual.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
Human temp;
try {
temp = new Human();
modelx.addHuman(indexPoint, temp);
///the addHuman method does display on jtable but doesn't increment arraylist, meaning that the size is always 0 which creates many problems/////
//modelx.add(indexPoint, temp); does indeed increment the arraysize but then it doesn't display the values on the jtable////
indexPoint++;
System.out.println(modelx.size());
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
newbiex.revalidate(); ////is the jtable////
}
});
here is my custom HumanListModel:
public class HumanListModel extends DefaultListModel implements TableModel
{
private ArrayList<Human> data;
public HumanListModel()
{
super();
data = new ArrayList<Human>();
}
public void addHuman(int k, Human h)
{
data.add(k, h);
fireIntervalAdded(this, data.size(), data.size());
}
public Human getHuman(int o)
{
return data.get(o);
}
public void removeHuman(Human h)
{
data.remove(h);
}
public int getColumnCount()
{
// the number of columns you want to display
return 1;
}
public int getRowCount()
{
return data.size();
}
public Object getValueAt(int row, int col)
{
return (row < data.size()) ? data.get(row) : null;
}
public String getColumnName(int col)
{
return "Human";
}
public Class getColumnClass(int col)
{
return Human.class;
}
public void addTableModelListener(TableModelListener arg0) {
}
#Override
public boolean isCellEditable(int arg0, int arg1) {
return false;
}
public void removeTableModelListener(TableModelListener arg0) {
}
public void setValueAt(Object arg0, int arg1, int arg2) {
}
}
You have to fire model changes when you change the data underlying the
public void addHuman(Human h)
{
data.add(h);
fireIntervalAdded(this, data.size(), data.size());
}
Similar methods with similar events need calling whenever you change the underlying data to tell the List that it has to update the screen image.
For example, removeHuman() will need a similar call. Consult the javadoc at http://docs.oracle.com/javase/6/docs/api/javax/swing/AbstractListModel.html for the methods that do that. (In this example, fireIntervalRemoved() and the event will need to contain the index of the row removed.)
You are going to also need a getElementAt() method that returns the data element for that row. In your case, return the Human at that row but it will need a toString() method. Alternately, you could format a string from the Human
and return it.
Note - A previous version of this answer was based on my confusion, thinking this was a TableModel and not a ListModel. It's been fixed.
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.