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().
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 !!
So I try to populate jtable using my arraylist, I also want to keep 3-layer architecture
My DAL
I read data from file and try to populate it into table
public class E {
public ArrayList<String> getinformationforthetable() {
Scanner s = null;
ArrayList<String> data = new ArrayList<String>();
try {
s = new Scanner(new File("songs.txt"));
while (s.hasNextLine()) {
String line = s.nextLine();
if (line.startsWith("")) {
String[] atoms = line.split("[#]");
ArrayList<String> row = new ArrayList<String>();
row.add(atoms[0]);
row.add(atoms[1]);
row.add(atoms[2]);
row.add(atoms[3]);
row.add(atoms[4]);
row.add(atoms[5]);
data.addAll(row);
}
}
}
catch(IOException e) {
e.printStackTrace();
}
finally {
if (s != null) {
s.close();
}
}
return data;
}
}
My UI
I want to populate table model with arraylist I had before but im not sure how to do it.
public class setTableModel extends AbstractTableModel{
private static final String[] COLUMN_HEADERS =
{
"Title", "Artist", "Gengre", "Quality", "Duration","Favorite"
};
private static final Class[] COLUMN_TYPES =
{
String.class, String.class,String.class,String.class, Integer.class, Boolean.class
};
#Override
public int getRowCount() {
return COLUMN_HEADERS.length;
}
#Override
public int getColumnCount() {
return null;
//todo
}
#Override
public Object getValueAt(int i, int i1) {
return null;
//todo
}
}
Don't use an ArrayList.
String[] atoms = line.split("[#]");
//ArrayList<String> row = new ArrayList<String>();
model.addRow( atoms );
You already have the data in an Array. You can use the addRow(...) method of the DefaultTableModel which will take the data in the array and add the data to the model for you.
So change your method signature. Instead of returning an ArrayList you should return a DefaultTableModel. Then you can use the model to create your JTable.
A problem I can see you facing is the structure of your ArrayList. It is only one dimensional. Data in a JTable/TableModel needs to be two dimensional rows/columns
If you made your getinformationforthetable() return an ArrayList<ArrayList<String>> then you would be able to more easily populate your table.
Also you might as well just extends DefaultTableModel. I don't see any special functionality added to your AbstractTableModel. Then you can just use the method addRow of DefaultTableModel to add rows. Something like this
DefaultTableModel model = new MyDefaultTableModel();
E e = new E();
ArrayList<ArrayList<String>> list = e.getinformationforthetable();
for (ArrayList<String> row : list) {
model.addRow(row.toArray());
}
table.setModel(model);
Or don't even extend DefaultTableModel at all. You can just override it's getColumnClass(), something like this
private static final String[] COLUMN_HEADERS =
{
"Title", "Artist", "Gengre", "Quality", "Duration","Favorite"
};
DefaultTableModel model = new DefaultTableModel(COLUMN_HEADERS, 0) {
#Override
public Class getColumnClass(int column) {
switch (column) {
case 0: return String.class; break;
case 1: return String.class; break;
...
}
}
};
In your example, you need your setTableModel (which you should rename to SetTableModel to be consistent with Java style) to maintain the data. Currently, you're keeping the data in E.
You can add a method to SetTableModel like addRow(String) and that method can do the split and keep the data within SetTableModel.
Then when you override getValueAt(int row, int column), you pull from the local data.
Also, getColumnCount() could return COLUMN_HEADERS.length and getRowCount() should return the number of rows maintained in the local data.
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.
Is there any way to add clickHandlers (or any type of handler) to the headers of the columns in a CellTable? I want to add some sorting functionality to my CellTable and I dont see any methods in the Column or Header classes that will allow this. I used this post to figure out how to use the CellTable.
Workaround for click events:
Header<String> columnHeader = new Header<String>(new ClickableTextCell()) {
#Override
public String getValue() {
return columnName;
}
};
columnHeader.setUpdater(new ValueUpdater<String>() {
#Override
public void update(String value) {
Window.alert("Header clicked!");
}
});
table.addColumn(column, columnHeader);
There is no out of the box way of supporting sort as yet on the CellTable. However there is a manual workaround involving a lot of code drudgery. Refer the classes SortableHeader and SortableColumn in the bike shed under expenses sample. You will find the usage in com.google.gwt.sample.expenses.gwt.client.ExpenseDetails. You can use this until something concrete comes out in the next release.
check out directory: http://google-web-toolkit.googlecode.com/svn/trunk/bikeshed
With the final release of GWT 2.1, has there been any support for sortable columns added to the CellTable? Or is it still a roll your own solution after looking at the bikeshed example?
CellTable<Contact> table = new CellTable<Contact>();
// Create name column.
final TextColumn<Contact> nameColumn = new TextColumn<Contact>() {
#Override
public String getValue(Contact contact) {
return contact.name;
}
};
// Create a data provider.
ListDataProvider<Contact> dataProvider = new ListDataProvider<Contact>();
// Connect the table to the data provider.
dataProvider.addDataDisplay(table);
final List<Contact> list = dataProvider.getList();
for (Contact contact : CONTACTS) {
list.add(contact);
}
final ListHandler<Contact> columnSortHandler = new ListHandler<Contact>(
list);
Header<String> columnHeader = new Header<String>(new ClickableTextCell()) {
#Override
public String getValue() {
return "Name";
}
};
columnHeader.setUpdater(new ValueUpdater<String>() {
#Override
public void update(String value) {
if (Window.confirm("Want to do?")){
nameColumn.setSortable(true);
columnSortHandler.setComparator(nameColumn,
new Comparator<Contact>() {
public int compare(Contact o1, Contact o2) {
if (o1 == o2) {
return 0;
}
// Compare the name columns.
if (o1 != null) {
return (o2 != null) ? o1.name.compareTo(o2.name) : 1;
}
return -1;
}
});
} else nameColumn.setSortable(false);
}
});
// Make the name column sortable.
nameColumn.setSortable(false);
// Create address column.
TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
#Override
public String getValue(Contact contact) {
return contact.address;
}
};
// Add the columns.
table.addColumn(nameColumn, columnHeader);
table.addColumn(addressColumn, "Address");
// Add the data to the data provider, which automatically pushes it to the
// widget.
// Add a ColumnSortEvent.ListHandler to connect sorting to the
// java.util.List.
//------------------ Code to add --------------------------------//
VerticalPanel vp = new VerticalPanel();
table.addColumnSortHandler(columnSortHandler);
//------------------ Code end --------------------------------//
// We know that the data is sorted alphabetically by default.
table.getColumnSortList().push(nameColumn);
// Add it to the root panel.
vp.add(table);
RootPanel.get().add(vp);