I have a JTable that is populated using a custom TableModel I created. I have another JTable that rows can be added to from the first JTable. I can add the row to the new JTable no problem, but I need to remove that row from the first JTable upon adding it to the new JTable. Unfortunately removeRow() is only a method for DefaultTableModel, and I've checked the source code on that and it doesn't show up...
Thanks in advance!
here's my custom table model:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package ttp;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.table.*;
import java.util.*;
/**
*
* #author ericrea
*/
/**creates the model for the accounts table*/
public class tableModel extends AbstractTableModel {
//private int rowCount = 0;
private static final int COLUMN_COUNT = 3;
private Conceptual_Package pp;
Conceptual_Package j = GUIpos.i;
public tableModel(Conceptual_Package pp) {
this.pp = pp;
}
/**sets the column headers*/
public String getColumnName(int i){
switch (i) {
case 0:
return "Sec";
case 1:
return "Row";
case 2:
return "Seat";
default:
return null;
}
}
/**figures out how many rows the model needs*/
public int getRowCount() {
int h = 0;
try {
h = Physical_PackageDAO.getInstance().getByConceptual_Package(j.getId()).size();
} catch (DataException ex) {
Logger.getLogger(tableModel.class.getName()).log(Level.SEVERE, null, ex);
}
return h;
}
/**Figures out number of columns*/
public int getColumnCount() {
return COLUMN_COUNT;
}
/**gets the account information from the Physical_Package*/
public Object getValueAt(int rowIndex, int columnIndex) {
String a = null;
String b = null;
String c = null;
try {
Physical_Package pp = Physical_PackageDAO.getInstance().getByConceptual_Package(j.getId()).get(rowIndex);
a = pp.getVenueSeat().getRowInVenue().getSectionInVenue().getSectionNumber();
b = pp.getVenueSeat().getRowInVenue().getRowNumber();
c = pp.getVenueSeat().getSeatNumber();
} catch (DataException ex) {
Logger.getLogger(tableModel.class.getName()).log(Level.SEVERE, null, ex);
}
switch (columnIndex) {
case 0:
return a.trim();
case 1:
return b.trim();
case 2:
return c.trim();
default:
return null;
}
}
/**gets the right account for the Physical_Package*/
public Physical_Package getCPackage(int index){
Physical_Package d = null;
try {
Physical_PackageDAO.getInstance().getByConceptual_Package(j.getId()).get(index);
} catch (DataException ex) {
Logger.getLogger(tableModel.class.getName()).log(Level.SEVERE, null, ex);
}
return d;
}
public void removeRow(int index){
}
//write in mainFrame, in panel
//ValueChanged{
// get the selected name
// Physical_Packages.get()
// namefield.settext(pp.getname);
//
//}
}
Unfortunately removeRow() is only a method for DefaultTableModel
Take a look at the source code for the DefaultTableModel. Both of these methods are implemented so you can use the code and an example of what your code might look like. The key ar the "fireXXX" methods. Invoking these methods will notify the table that the model has changed so the table can repaint itself.
From your older question (which you just deleted) you state "I can add the row to the new jTable no problem,"
From looking at your code (before you deleted the question) I have the following comment:
Its looks to me like you are creating a completely new TableModel. That is not the same as adding a row to an existing model. That does not seem like a very good solution. Instead you need to create an addRow(...)
If you find the code too confusing in the DefaultTableModel, then here is some code that shows how I've implemented addRow(...) and removeRow(...) methods. See Row Table Model. The class shows the proper fireXXX methods to use for each method.
Related
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.
I have An Object called Student and in this Object i have A arrayList of Object That Contains material(name,note)
Public Class Student{
private String StudentFirstName;
private String StudentLastName;
private List<Material> materials;
}
public Class Material{
String String materialName;
String Float note;
}
i want to display All Data in Jtable like that:
StudentFirstName:Jack StudentLastName:Dupont materialName:Math note:15
StudentFirstName:Jack StudentLastName:Dupont materialName:french note:12
StudentFirstName:Jack StudentLastName:Dupont materialName:Math note:15
StudentFirstName:Jack StudentLastName:Dupont materialName:Sport note:10
StudentFirstName:peter StudentLastName:sanchez materialName:Math note:14
StudentFirstName:peter StudentLastName:sanchez materialName:french note:17
StudentFirstName:peter StudentLastName:sanchez materialName:Arabic note:11
this Is My Table Model
package com.orange.tableModel;
public class DataTableModel extends AbstractTableModel {
String[] entete = {"StudentFisrtName", "StudentLastNameName",
"Mat erialName", "MaterialNote"};
List<Student> allStudents;
public DataTableModel() {
allStudents = new ArrayList<>();
}
#Override
public int getRowCount() {
return allStudents.size();
}
#Override
public int getColumnCount() {
return entete.length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0: {
return allStudents.get(rowIndex).getStudentFirstName();
}
case 1: {
return allStudents.get(rowIndex).getStudentLastName();
}
case 2: {
return allStudents.get(rowIndex).materials(rowIndex).getMaterialName();
}
case 3: {
return allStudents.get(rowIndex).materials(rowIndex).getNote();
}
default:
throw new IllegalArgumentException();
}
}
#Override
public String getColumnName(int column) {
return entete[column];
}
}
Jtable dataTable=new Jtable();
dataTable.setModel(new DataTableModel()); `
So the result Is:
StudentFirstName:Jack StudentLastName:Dupont materialName:Math note:15
StudentFirstName:peter StudentLastName:sanchez materialName:Math note:14
I'll do something like this:
First of all, the method getRowCount()
returns allStudents.size()
and actually this value is two, so you tell to your DataTableModel that your tables contains 2 rows and that is incorrect.
Try to modify this method doing something like that:
#Override
public int getRowCount() {
int row_count=0;
for (int i=0; i<allStudents.size(); i++) {
row_cont+=allStudents.get(i).getMaterials().size();
}
in this way, you'll force the jtable to have how many rows you need. Next, you should write a smarter method getValueAt. You should maintain a variable (e.g. count_row) that tells you how many rows are dedicated to the same Student and doing a control over that, for example
if (count_row< allStudents.get(rowIndex).getMaterials().size()) {
//show information of the same Student but with materials(count_row)
}
or something like this. In a nutshell, you tell to your jTable to display the same Student until every Material is displayed.
You can solve this problem following another way: you should create an ArrayList with redundant data, for example doing something like this
Student A_B=new Student("A","B","Math",12); //first_name, last_name, subject, note
Student A_B=new Student("A","B","History",4);
Student B_C=new Student("B","C","Geograph",10);
Hope that this can be to you an useful tip. Hi !!
Currently I have a DerbyDB and a UI with a JTable on it. Now I also I have a bunch of classes but the ones I need help with is SensorDBConnection and myUI. myUI is where have my JTable, and what I want to do is update my JTable from my query which is located on my SensorDBConnection
The following is a snippet from my SensorDBConnection which works because it is doing System.outs
DefaultTableModel model;//Confused
model = new DefaultTableModel(); //Confused
jTable1 = new JTable(model);//Confused
model.addColumn("TIME");
model.addColumn("SENSORID");
model.addColumn("TEMP");
model.addColumn("HUM");
model.addColumn("LIGHT");
model.addColumn("VOLTAGE");
while(results.next())
{
time = results.getInt(1);
id = results.getInt(2);
temp = results.getInt(3);
hum = results.getInt(4);
light = results.getInt(5);
voltage = results.getInt(6);
model.addRow(new Object[]{time,id,temp,hum,light,voltage});
Sensor sens = new Sensor(id, temp, hum, light, voltage);
sensors.add(sens);
//System.out.println(sens);
}
results.close();
stmt.close();
So essentially what I am doing right now is querying my data, and then trying to Push it to my JTabel located on my other class, and I don't know how to create the link between them..
Start by separating your UI from you data management. Instead of having SensorDBConnection return a TableModel, have it return the data that would be required to build a data model...
For example...
public class SensorDBConnection extends ... {
public List<Sensor> loadData() {
List<Sensor> sensors = new ArrayList<>(25);
try {
//...
while(results.next())
{
time = results.getInt(1);
id = results.getInt(2);
temp = results.getInt(3);
hum = results.getInt(4);
light = results.getInt(5);
voltage = results.getInt(6);
model.addRow(new Object[]{time,id,temp,hum,light,voltage});
Sensor sens = new Sensor(id, temp, hum, light, voltage);
sensors.add(sens);
}
} finally {
try {
results.close();
} catch (Exception exp) {
}
try {
stmt.close();
} catch (Exception exp) {
}
}
return sensors;
}
}
Then, in MyUI, you would simply request the sensor data and build your TableModel. To make your life simpler, create a custom TableModel which knows how to deal with Sensors...
public class SensorTableModel extends AbstractTableModel {
protected static final String[] COLUMN_NAMES = {
"TIME",
"SENSORID",
"TEMP",
"HUM",
"LIGHT",
"VOLTAGE"
};
private List<Sensor> sensors;
public SensorTableModel(List<Sensor> sensors) {
this.sensors = sensors;
}
#Override
public String getColumnName(int column) {
return COLUMN_NAMES[column];
}
#Override
public int getRowCount() {
return sensors.size();
}
#Override
public int getColumnCount() {
return COLUMN_NAMES.length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Sensor sensor = sensors.get(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = sensor.getTime();
break;
case 1:
value = sensor.getID();
break;
case 2:
value = sensor.getTemp();
break;
case 3:
value = sensor.getHum();
break;
case 4:
value = sensor.getLight();
break;
case 5:
value = sensor.getVoltage();
break;
}
return value;
}
}
Then simply call the loadData method from SensorDBConnection in your MyUI class and simply create an instance of the TableModel and apply it to theJTable` instance you already have...
public class MyUI extends ... {
private JTable table;
private SensorDBConnection sensor;
//...
protected void loadTableContents() {
TableModel model = null;
try {
model = new SensorTableModel(sensor.loadData());
} catch (SQLException exp) {
// Handle exception
}
table.setModel(model);
}
}
For example...
If I understood your question correctly, you should be able to create an instance of SensorDBConnection in myUI. That way you may call the methods, queries, etc ... of SensorDBConnection within myUI.
I would create my own subclass of TableModel that is specific to the data being returned. Then once you set the data in the TableModel to the new data, call fireTableDataChanged().
I'm using Glazed lists, in a jTable where I have a column which is boolean.
By default the jTable renders a checkbox where the column is type Boolean.Class.
Using Glazed lists i cannot get the checkbox which is needed. I rendered checkboxs extending the DefaultTableCellRenderer but i'm not satisfied with it because the checkboxs are not "clickable".
In the GL faq http://www.glazedlists.com/documentation/faq i found:
*Q: How do I specify that my boolean table cells be rendered with a checkbox?
For some reason, Glazed Lists has no getColumnClass() method.
A: If you need to specify the column class, you need to implement the AdvancedTableFormat interface instead of the regular TableFormat class.
If you are using the GlazedLists.tableFormat() factory method, you must specify the base Object's class for a proper implementation of the AdvancedTableFormat.getColumnClass() method.*
Does some of you have experience with this I did not find any links with an example. The essential link in the faq is broken.
I tried with this:
public class CheckBoxTableModel implements AdvancedTableFormat {
public Class getColumnClass(int column) {
if(column==4)
return Boolean.class;
else
return Object.class;
}
}
Please help!
EDIT:
I tried with this, the form with the jtable does not show
private class TicketTableFormat implements AdvancedTableFormat<Ticket> {
private final String[] cols = new String[]{"Id", "From", "Subject", "Date", "Incomplete"};
public int getColumnCount() {
return cols.length;
}
public String getColumnName(int colId) {
return cols[colId];
}
public Class getColumnClass(int col) {
if (col == 4) {
return Boolean.class;
} else {
return Object.class;
}
}
public Object getColumnValue(Ticket ticket, int colId) {
switch (colId) {
case 0:
return ticket.getId();
case 1:
return ticket.getFrom();
case 2:
return ticket.getSubject();
case 3:
return ticket.getDate();
case 4:
return ticket.getIncomplete();
}
return null;
}
public boolean isEditable(Ticket e, int col) {
if (col < 4) {
return false;
} else {
return true;
}
}
public Ticket setColumnValue(Ticket e, Object o, int i) {
e.setB((Boolean) editedValue);
return e;
}
public Comparator getColumnComparator(int i) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
i call it with this:
TicketTableFormat tbFormat = new TicketTableFormat();
TicketsModel = new EventTableModel(textFilteredTickets, tbFormat);
ticketTable.setModel(TicketsModel);
The basic point here is that rendering table cells and eiting them are two different things. For table cell rendering, the renderer only serves as a 'stamp', i.e. the check box is initialized to the state that should be rendered and aterwards the Table only takes apicture of the renderer (by invoking its paint method) and places the tat picture in the appropriate cell - for rendering all the cells, the same instance of checkbox is re-configured over and over again to represent the according cell value. What you did in your code, is specifying the data type flavor of the model, so that the default table cell renderer chosen by the table is a checkbox renderer.
For the checkbox to be editable, a cell editor must be attached to the table cell (e.g. by configuring an editor for the particular column). In case a table cell receives input focus, the table cell editor component is initialized and placed inside the table cell (i.e. above the image that was painted by the renderer before). This cell editor component (would be a checkbox in your case) is remainig there (accepting user input via mouse or keyboard) until the user navigates away from that particzular table call. In the moment when editing ends, the cell editor is asked for the vale it has captured from the editing process, (i.e. getCellEditorValue() is called on the editor) and hte value is taken by the table and written back to the table model for that cell.
So in short: The renderer is only stamping data on the cell, i.e. outputting, an editor component is necessary to receive input.
Example code for custom table cell editor
Java tuorial explaining the thing in detail and having also checkbox examples and code
Did you implement isEditable(...) & setColumnValue(...) in your implementation of AdvancedTableFormat?
Implementing the following methods works for me.
public int getColumnCount()
public String getColumnName(int column)
public Object getColumnValue(E model, int column)
public boolean isEditable(E model, int column) // For making the checkbox editable
public IFdsModel setColumnValue(E model, Object value, int column)
public Class getColumnClass(int column) // For making it a Checkbox
public Comparator<E> getColumnComparator(int arg0) // for sorting (if you have a SortedList)
Edit: an example (quick and dirty)
import java.util.Comparator;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.gui.AdvancedTableFormat;
import ca.odell.glazedlists.gui.WritableTableFormat;
import ca.odell.glazedlists.swing.EventTableModel;
public class Tester {
private static class MyBoolean {
private Boolean b = Boolean.FALSE;
public Boolean getB() {
return b;
}
public void setB(Boolean b) {
this.b = b;
}
}
private static class BooleanTableFormat implements AdvancedTableFormat<MyBoolean>, WritableTableFormat<MyBoolean> {
#Override
public int getColumnCount() {
return 1;
}
#Override
public String getColumnName(int column) {
return "Bool";
}
#Override
public Object getColumnValue(MyBoolean baseObject, int column) {
return baseObject.getB();
}
#Override
public Class getColumnClass(int column) {
return Boolean.class;
}
#Override
public Comparator getColumnComparator(int column) {
throw new IllegalStateException("Not yet implemented.");
}
#Override
public boolean isEditable(MyBoolean baseObject, int column) {
return true;
}
#Override
public MyBoolean setColumnValue(MyBoolean baseObject, Object editedValue, int column) {
baseObject.setB((Boolean) editedValue);
return baseObject;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
EventList<MyBoolean> list = new BasicEventList<MyBoolean>();
list.add(new MyBoolean());
list.add(new MyBoolean());
EventTableModel<MyBoolean> etm = new EventTableModel<MyBoolean>(list, new BooleanTableFormat());
JTable table = new JTable(etm);
JFrame f = new JFrame("Tester");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 200);
f.getContentPane().add(new JScrollPane(table));
f.setVisible(true);
}
});
}
}
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.