Update Table GUI that extends custom AbstractTableModel - java

I created a Java GUI that displays the table using the following syntax:
table = new JTable(new MyTableModel(columnNames,
updateTable(cmbAdversary.getSelectedItem().toString(),
cmbdataType.getSelectedItem().toString())));
where columnNames is a Vector of Strings
cmbadversary and smbdataType are the selection od combo boxes.
and updateTable is a method that returns a Vector of Vectors depending on the combo box selection as follows:
static Vector updateTable(String FilterVal1 , String FilterVal2)
{
try {
myVector = tssc.testSeverityFunctionService(FilterVal1,FilterVal2);
} catch (Exception e) {
e.printStackTrace();}
return myVector;
}
This is how my custom class MyTableModel that extends AbstractTableModel looks like:
class MyTableModel extends AbstractTableModel
{
Vector columnNames = new Vector();
Vector Fdb = new Vector();
public MyTableModel(Vector cName,Vector rName){
this.columnNames = cName;
this.Fdb = rName;}
public int getColumnCount() { // number of columns in the model.
return columnNames.size();
}
public int getRowCount() { // number of rows in the model.
return Fdb.size();
}
#Override
public String getColumnName(int col) {
return columnNames.get(col).toString();
}
public Object getValueAt(int row, int col) {
Vector v = (Vector) this.Fdb.get(row);
return v.get(col);
}
#Override
public Class getColumnClass(int c) {
Vector v = (Vector) Fdb.get(0);
return v.get(c).getClass();}
public boolean isCellEditable(int row, int col)
{ return true; }
public void setValueAt(Vector value, int row, int col)
{
for(int i=0;i<value.size();i++)
{ for(int j=0;j<columnNames.size();j++) {
Fdb.setElementAt(value.get(j),j); }
}
fireTableCellUpdated(row, col);
}
}
The problem is that when I run the code, the table GUI show me initial values but fails to update when I change the selection in the 2 comboboxes and click the selection button.
The Selection button, btw, calls a method which implements the action listener.
Please help me out. Am no pro in Java, but willing to learn. If you have any followup qs., I'll be happy to provide details.

Your solution seems overly complicated. If I understand the basics, the user chooses a value from a combo box, then based on the selection some data is loaded into the table.
There is no need to create a custom table model to do this.
A TableModel contains data. If you want to change the data, then one way to do this is to simply create a new TableModel. So you add an ActionListener to your combo box. When an item is selected you retrive your data and load the data into an Vector or an Array. Using this data you can create a new TableModel and update the JTable in two lines of code:
DefaultTableModel model = new DefaultTableModel(...);
table.setModel( model );
If you need to customize the model to override the getColumnClass() or isCellEditable() methods, then you should extend the DefaultTableModel. I don't see any need to implement the whole model.

Related

CheckBox in jTable?

I've added a checkbox to rows on my table, but unfortunately I'm unable to select/deselect them.
I'm using an own Table Model that I got on internet.
Table Model's code:
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
/**************/
public class ModeloTabela extends AbstractTableModel {
private ArrayList linhas = null;
private String [] colunas = null;
public ModeloTabela(ArrayList lin, String[] col){
setLinhas(lin);
setColunas(col);
}
public ArrayList getLinhas(){
return linhas;
}
public void setLinhas(ArrayList dados){
linhas = dados;
}
public String[] getColunas(){
return colunas;
}
public void setColunas(String [] nomes){
colunas = nomes;
}
public int getColumnCount(){
return colunas.length;
}
public int getRowCount(){
return linhas.size();
}
public String getColumnCount (int numCol){
return colunas[numCol];
}
public Object getValueAt(int numLin, int numCol){
Object[] linha = (Object[])getLinhas().get(numLin);
return linha[numCol];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public boolean isCellEditable(int row, int col) {
return true;
}
}
And this Method will fill the Table:
public void PreencheTabela(String sql, JTable jt1, JTextField j1){
c.conexao();
ArrayList dados = new ArrayList();
String [] Colunas = new String[] {"STATUS", "ID", "FABRICANTE", "FORNECEDOR", "NOME", "CATEGORIA", "DATA DO CADASTRO", " CODIGO DE BARRAS", "QUANTIDADE"};
c.executaSQL(sql);
try {
c.rs.first();
do{
dados.add(new Object[]{c.rs.getInt("prod_id"),c.rs.getString("prod_fabricante"),c.rs.getString("prod_fornecedor"),c.rs.getString("prod_nome"),
c.rs.getString("prod_categoria"),c.rs.getDate("prod_datacadastro"),c.rs.getString("prod_codbarras"), c.rs.getInt("est_quantidade")});
j1.setBorder(BorderFactory.createLineBorder(Color.black));
}while(c.rs.next());
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro!\n"+ex.getMessage());
}
ModeloTabela modelo = new ModeloTabela(dados, Colunas);
jt1.setModel(modelo);
}
Which code can I use? Also, where do I put this code??
but unfortunately I'm unable to select/deselect them.
You didn't implement the setValueAt(...) method in your TableModel so the value can never be updated in the model.
I'm using an own Table Model that I got on internet.
Why are you using a custom TableModel? You can use the DefaultTableModel. It implements the setValueAt(...) method correctly. It also has an addRow(..) method that allows you to dynamically update the model.
Are you actually storing Boolean objects in the TableModel? I don't see you using getBoolean() to get the data from your ResultSet. The default renderers/editors for a check box will only be used when you have Boolean data in the column.
Also take a look at: Can't create column with checkboxes in JTable for a better implementation of the getColumnClass() method.
If you insist on using your custom TableModel, then take a look at the Swing tutorial link you were given in your last question. It shows and example of implementing the setValueAt() method.

Display a JTable [duplicate]

This question already has an answer here:
Store products in a TreeSet and print the content in a JTable
(1 answer)
Closed 7 years ago.
I'm trying to display a single JTable, but I keep getting many new JTables everytime I insert a new product: http://i.stack.imgur.com/gyNsn.png
How can I display just one JTable and also make the column names visible?
Here is the method that creates the table:
public JTable populate(Product p) {
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
Vector<Object> row = new Vector<Object>();
Vector<String> headers = new Vector<String>();
headers.add("Product name");
headers.add("Price");
headers.add("In stock");
row.add(p.getProductName());
row.add(p.getPrice());
row.add(p.getStock());
data.add(row);
productsTable = new JTable(data, headers);
return (new JTable(data, headers));
}
And here is a part from the GUI class:
addProductBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Product product = new Product(insertProductName.getText(), Integer.parseInt(insertPrice.getText()), Integer.parseInt(insertStock.getText()));
warehouse.addProduct(product); // by using a TreeSet
productsTable = warehouse.populate(product); // here I call the earlier defined method
warehouse.initFile(); // I wrote the productsTable content into a binary file, so that it can act like a database
warehouse.readFile();
warehouse.populate(product);
manageProductsPanel.add(productsTable);
});
The populate method you posted creates a new JTable every time it is called. Given this is called every time the ActionListener is called, a new JTable will be added. You should consider creating your own TableModel - extend AbstractTableModel and override the necessary methods, returning the appropriate values for each row/column. A simple example is below, making some assumptions about project structure for demo's sake (for instance warehouse is an instance of a List):
public class MyTableModel extends AbstractTableModel{
#Override
public int getColumnCount() {
return 3;
}
#Override
public int getRowCount() {
return warehouse.size();
}
#Override
public Object getValueAt(int arg0, int arg1) {
switch(arg1){
case 0:
return warehouse.get(arg0).getName();
case 1:
return warehouse.get(arg0).getPrice();
default:
return warehouse.get(arg0).isInStock();
}
}
#Override
public String getColumnName(int col){
switch(col){
case 0:
return "Name";
case 1:
return "Price";
default:
return "In STock";
}
}
}
You can then create an instance of this class, and set the table model for the JTable. Every time the backed List is updated, you can update the Listeners of the TableModel
MyTableModel tableModel = new MyTableModel();
myTable.setMOdel(tableModel);
.......
//when an item is added to
warehouse.add(item);
tableModel.fireTableDataChanged();
There are more demonstrations for how to customize a JTable in the Oracle Tutorials

How to change value of a cell in a table model in Java?

I created a class inheriting from AbstractTableModel. I want to override setValueAt(), so that it will change the value of the cell in row r and column c into the multidimensional array v. But I keep getting errors.
public class ItemListTableModel extends AbstractTableModel{
public void setValueAt(Object v, int r, int c) {
rowData[r][c] = v;// This is where the error is.
fireTableCellUpdated(r, c);
}
#Override
public int getRowCount() {
}
#Override
public int getColumnCount() {
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
}
public boolean isCellEditable(int row, int col){
return true;
}
}
AbstractTableModel has no concept of the content of the model or how it's managed, that's kind of the point. It's designed to allow developers to design their own models based on their own complex requirements.
A simpler solution would be to use a DefaultTableModel, which provides all the functionality out of the box...
DefaultTableModel model = new DefaultTableModel(rows, columns); // you need to define rows and columns for yourself
model.setValueAt(row, column, value); // Again, you need to define the variables for your self
Should you "absolutely" need a custom table model based on AbstractTableModel, then you will need to provide the storage mechanisms which are used to store data within a given row/data yourself.
Typically, I define a POJO which represents the row and then add these to some kind of List, as it provides a simple mechanism for growing and shrinking the model
In your class you haven't declared the type of rowData. Presumably it's an 2 x 2 int array, but you haven't declared it, so the compiler cannot find the identifier. What you want to do is first declare rowData like
int[][] rowData = new int[r][v];
Then you can assign v to rowData as normal.
Example use of AbstractTableModel::setValueAt().
class MyTableModel extends AbstractTableModel {
private final String[] columnNames = new String[]{"Col One", "Col Two"};
private final Object[][] data = new String[][]{new String[]{"R1C1", "R1C2"}, new String[]{"R2C1", "R2C2"}};
#Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
......
rest of the code

Automatic row numbering in javafx table

I have a sample code that we use to dynamic row numbers in Java Swing Table i.e JTable. I new to JavaFX and would like to the same in JavaFX. Is there is any way to set automatic row numbers in JavaFX Table
class LineNumberTable extends JTable {
private JTable mainTable;
public LineNumberTable(JTable table) {
super();
mainTable = table;
setAutoCreateColumnsFromModel(false);
setModel(mainTable.getModel());
setAutoscrolls(false);
addColumn(new TableColumn());
getColumnModel().getColumn(0).setCellRenderer(mainTable.getTableHeader().getDefaultRenderer());
getColumnModel().getColumn(0).setPreferredWidth(40);
setPreferredScrollableViewportSize(getPreferredSize());
}
#Override
public boolean isCellEditable(int row, int col) {
if (col == uneditableColumn) {
return false;
}
return bEdit;
}
#Override
public Object getValueAt(int row, int column) {
return Integer.valueOf(row + 1);
}
#Override
public int getRowHeight(int row) {
return mainTable.getRowHeight();
}
}
In JavaFX, you use TableColumns with CellFactories and CellValueFactories to populate your TableView.
The JavaFX tutorials have an article that might get you started.
In one approach I have used I convert the business objects to display into presentation objects and add all necessary properties (like in your case, the number) to them.
EDIT: In a second, cleaner approach, you could set your CellFactory to create a TableCell that shows its own index property in TableCell#updateItem(S, boolean):
public class NumberedCell extends TableCell{
protected void updateItem(Object object, boolean selected){
setText(String.valueOf(getIndex());
}
}

Java JTable restructure / reload / refresh

I have a tree and a table on my panel, when I click the tree node, the table needs to change at the same time, but it doesn't. I search online and read the Java tutorial and didn't find any solutions. From some posts I think I need to use fireTableStruetureChanged(), but it just doesn't work in my code. Could anyone help me out of this? The following is the code. Thanks a ton!
public class tableStructureChange extends JFrame implements ... {
.....
/ //columnNames is a public variable, because I need to change the columns later
columnNames = new String[] {"col1","col2"}; */
data = new String[][]{
{"Mary", "Campione"},
{"Alison", "Huml"}, };
table = new JTable(new MyTableModel());
table.setAutoCreateColumnsFromModel( false );
feedback = new JScrollPane(table); //feedback is the bottom panel
...
}
//the following class is the problem, i need the table to be reloaded
//when the class is called, but the table doesn't change at all
public void displayFeedback(String tempString) {
//create table for bottom panel
columnNames = new String[] {"col3","col4", "col5"};
String[][] data = new String[][]{
{"Mary", "Campione", "us"},
{"Alison", "Huml", "canada"}, };
//table = new JTable(data, columnNames);
//fireTableStructureChanged(); //this is the problem part
}
// my table model
class MyTableModel extends AbstractTableModel {
String[] columnNames = new String[] {"col1","col2"};
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];
}
}
...
}
In your method displayFeedback you seem to be hoping to replace the JTable object and have the display change to reflect what is selected in the JTree above. Instead of replacing what is in the View object, you should focus your effort on updating the Model, in this case, the AbstractTableModel subclass that you have created. There are a couple ways you can do that, but for a brute force proof of concept, you could do something like the following:
add a constructor to MyTableModel that takes a 2 dimensional array of data
in displayFeedback, create a new instance of MyTableModel that has new data relevant to the tree node that was selected.
call setModel on your global table variable.

Categories

Resources