I am wondering if it is possible to refresh a Table's GUI when the Object[][] used to initially populate it has changed.
Object[][] calculationsTableData;
public Interface() {
...
analysisPanel.add(calculationsTable());
...
}
JScrollPane calculationsTable() {
populateCalculationsTableData();
...
calculationsTable = new JTable(calculationsTableData, calculationsColumnNames);
...
}
void populateCalculationsTableData(){
Object[][] temp = new Object[x.numsSize][7];
for (int i = 0; i < x.numsSize; i++) {
temp[i][0] = df.format(x.nums[i]);
...
}
calculationsTableData = temp;
}
populateCalculationsTableData() is called when the x object has changed to repopulate calculationsTableData
repaint() and revalidate() methods do not appear to be effective in this scenario and neither does fireTableDataChanged() as this is not a table model.
By default JTable creates a new instance of DefaultTableModel AbstractTableModel [1] implementation if no table model is explicitely set. If the table needs to be updated you have to work with its model.
You could...
Set a new DefaultTableModel:
void populateCalculationsTableData() {
...
calculationsTableData = temp;
TableModel model = new DefaultTableModel(calculationsTableData, calculationsColumnNames);
calculationsTable.setModel(model);
}
Or you could...
Create the table using a DefaultTableModel:
TableModel model = new DefaultTableModel(calculationsTableData, calculationsColumnNames);
calculationsTable = new JTable(model);
Cast the table model as DefaultTableModel and set its data and columns like this:
void populateCalculationsTableData() {
...
calculationsTableData = temp;
DefaultTableModel model = (DefaultTableModel)calculationsTable.getModel();
model.setDataVector(calculationsTableData, calculationsColumnNames);
}
Suggested readings
JTable(Object[][] rowData, Object[] columnNames)
DefaultTableModel#setDataVector(Object[][] dataVector, Object[] columnIdentifiers)
How to Use Tables
[1]: After checking JTable(Object[][] rowData, Object[] columnNames) source code I've realized that no DefaultTableModel is created but a new anonymous inner class extending from AbstractTableModel instead.
I would create your own table model to wrap the object arrays, and which exposed the fireTableDataChanged() method:
private static class ObjectArrayModel extends AbstractTableModel {
private final Object[][] rowData;
private final Object[] columnNames;
private ObjectArrayModel(Object[][] rowData, Object[] columnNames) {
this.rowData = rowData;
this.columnNames = columnNames;
}
#Override
public void fireTableDataChanged() {
super.fireTableDataChanged();
}
public String getColumnName(int column) {
this.fireTableDataChanged();
return columnNames[column].toString();
}
public int getRowCount() {
return rowData.length;
}
public int getColumnCount() {
return columnNames.length;
}
public Object getValueAt(int row, int col) { return rowData[row][col]; }
public boolean isCellEditable(int row, int column) { return true; }
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = value;
fireTableCellUpdated(row, col);
}
}
... when the data changes you should be able to call fireTableDataChanged() on this and it will notify the table it needs to redraw itself.
Related
I'm looking for a way to make data entries for a table from data collected from a SQL database. I have the code made for grabbing the data from the database but I need help with turning that data into table entries
First create an object to represent each row in the table.
public class MyData {
private String name;
private String desc;
//add getters/setters
}
Then you should create a table model
public class MyTableModel extends AbstractTableModel {
List<MyData> list = new ArrayList<>();
public void addRow(MyData data) {
list.add(data);
fireTableRowsInserted(list.size()-1, list.size()-1);
}
//then fill in the required method
public String getColumnName(int col) {
switch (col) {
case 0:
return "Name";
case 1:
return "Description";
}
return "";
}
public int getRowCount() {
return list.size();
}
public int getColumnCount() {
return 2; //or however many columns you need
}
public Object getValueAt(int row, int col) {
MyData data = list.get(row);
if (col == 0) {
return data.getName();
} else if (col == 1) {
return data.getDesc();
}
return null;
}
}
Then use that model in your table;
MyTableModel tableModel = new MyTableModel();
JTable table = new JTable(tableModel);
Then you you can read data from the database you just have to call
tableModel.add(data);
I'm trying to use a custom TableModel in my java desktop application. The GUI has been made using NetBeans.
But the thing is when I use the DefaultTableModel then I can see my table in the design view of the GUI.
But when I use my custom TableModel then It is not displayed in the design view, although it is displayed when I run the application.
What seems to be the problem?
Custom Table Model Code
public class BillingTableModel extends AbstractTableModel implements TableModel {
String columnNames[] = {
"Name", "Address", "1", "2", "3"
};
Object data[][] = {
{null,null,null,null,null},
{null,null,null,null,null},
{null,null,null,null,null},
{null,null,null,null,null},
{null,null,null,null,null}
};
Class types[] = new Class [] {
String.class, String.class, String.class, String.class, String.class
};
#Override
public Class<?> getColumnClass (int columnIndex) {
return types[columnIndex].getClass();
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
#Override
public boolean isCellEditable (int row, int col) {
if (col >= 2)
return true;
else
return false;
}
#Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
I edited the default code to include my class like this
customerTable = new javax.swing.JTable();
customerTable.setModel(new BillingTableModel());
tableScrollPane.setViewportView(customerTable);
Subclass JTable and then you can drag your custom JTable to the Netbeans designer instead of a regular JTable and your custom model will already be visible.
eg.
Put this file in your project as CustomerTable.java
public class CustomerTable extends JTable {
public CustomerTable() {
this.setModel(new BillingTableModel());
}
}
Select the file and choose Run -> Compile File from the Menu. (or press F9)
Delete the JTable you have from your the Netbeans Design view, and drag CustomerTable.java from the projects window into the design view instead.
I have created a JTable using Abstract Table Model. This table has a two dimensional array of Integer object data and one 1 dimensional column header.Everything works fine except when I edit & change the cell data during program's runtime, it reverts back to the default value (created with getValueAt()). I have implemented Abstract Table Models setValueAt() method but it does not work.
Can anyone please tell me whats is wrong in my code?
import javax.swing.table.AbstractTableModel;
public class TableModel1 extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
String [] colNames=new String[30];
Object[][] data= new Integer[4][30];
#Override
public int getColumnCount() {
return colNames.length;
}
#Override
public int getRowCount() {
return 4;
}
public String getColumnName(int col){
if (col==0){
colNames[0]="Boarders";
}
else if(col>0){
for(int i=1;i<colNames.length;i++){
colNames[i]=new String(""+i);
}
}
return colNames[col];
}
#Override
public Object getValueAt(int row, int col) {
for(int i=0; i<data.length;i++){
for(int j=0; j<data[i].length;j++){
data[i][j]=new Integer(1);
}
}
return data[row][col];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public boolean isCellEditable(int row, int col){
return true;
}
public void setValueAt (Object aValue, int row, int col){
data[row][col]=(Integer)aValue;
fireTableCellUpdated(row,col);
}
}//end class
Seems that happens because when getValueAt() method invokes, you always refresh data in your array with next lines:
for(int i=0; i<data.length;i++){
for(int j=0; j<data[i].length;j++){
data[i][j]=new Integer(1);
}
}
So, remove this lines from getValueAt() method, and initialize your array in constructor of your model only once not every time as now.
the problem is in the getValueAt . those methods are constantly called. its not a one time thing. initiate the values outside of the table model
I'm developing a software for my friend.I have developed 90% of my project and my problem is I have a table which I fill with data in database.I have used a custom table model to fill jtable. It fills data perfectly but the problem is it doesn't contain proper column header instead of that it contain A,B,C for column headers .
here is my custom table model class.
public class SellUpdateModel extends AbstractTableModel
{
private Vector<Vector> data;
public SellUpdateModel(String Jid)
{
data = new Vector<>();
data = new JobDetailsDAO().get_ItemDescriptionAndQuantity(Jid); //Retrive data from databse and fill it to vector.
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return false; // does not allowed to edit cells
}
#Override
public int getRowCount()
{
return data.size();
}
#Override
public int getColumnCount()
{
return 3;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex)
{
return data.elementAt(rowIndex).elementAt(columnIndex);
}
public SellUpdateModel deleteRow(int row, Vector pData)
{
data.remove(data.elementAt(row)); // remove a record from vector
data.add(pData); // add a record to vector
return this;
}
}
You have to override getColumnName(int columnIndex).
public class SellUpdateModel extends AbstractTableModel {
private final String[] tableHeaders = {"X", "Y", "Z"};
#Override
public String getColumnName(int columnIndex) {
return tableHeaders[columnIndex];
}
}
I have a LinkedHashSet of Book objects. The Book objects have the following fields:
private int id;
private String author = "";
private String title = "";
private boolean isRead;
private String dateStamp = "";
private static int counter = 0;
I want them to go into my JTable which has the following columns:
String [] columnNames = {"ID","Title", "Author", "Status", "Date Read"};
How can I do this? And is it possible to have the isRead field being editable through a checkbox in the table?
You need to have a class that extends AbstractTableModel. This class should use your LinkedHashSet as the data source for your table. The basic implementation provided by AbstractTableModel should suit most of your needs. If not, then you can override the methods you need to customize.
This tutorial should help you understand how JTable objects work.
This is a sample model I have created for the table.
public class CustomModel extends AbstractTableModel {
private Object[] colNames ={"ID","Title", "Author", "Status", "Date Read"};
private LinkedHashSet<CustomClass> data;
public TableModelTop() {
this.data = getDataForDropList();
}
public int getRowCount() {
return data.size();
}
public int getColumnCount() {
return colNames.length;
}
#Override
public String getColumnName(int columnIndex) {
return (String) colNames[columnIndex];
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
// Set Values here;
}
public Object getValueAt(int rowIndex, int columnIndex) {
// Get row Values here;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
// Depending on the type of the column. Return data type;
}
/**
* Populate the data from here.
* #return LinkedHashSet<CustomClass>
*/
private LinkedHashSet<CustomClass> getDataForDropList() {
LinkedHashSet<CustomClass> modelList = new LinkedHashSet<CustomClass>();
for(int i = 0; i< 5; i++) {
// Create custom Object and add them to the LinkedHashSet.
// Create a CustomClass object and add it to the LinkedHashSet
modelList.add(customClassObject);
}
// Finally return the llinkedhashset
return modelList;
}
}
After this just call the table model and assign this to the JTable.
JTable table = new JTable(new CustomModel());
As a concrete example of using AbstractTableModel, you can leverage the toArray() method inherited by LinkedHashSet to simplify the implementation of getValueAt(), as shown in this related EnvTableTest. The default JTable renderer and editor use JCheckBox for TableModel elements of type Boolean.class, as shown in this example.