Populating a JTable using ArrayList<String> - java

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.

Related

JTable populated from an ArrayList

What I am trying to do is to populate a JTable from an ArrayList.
The array list is a type Record which I have defined below:
public class Record {
int Parameter_ID;
int NDC_Claims;
int NDC_SUM_Claims;
public Record(int parameter, int claims, int ndc_sum_claims){
Parameter_ID = parameter;
NDC_Claims = claims;
NDC_SUM_Claims = ndc_sum_claims;
}
public Record() {
// TODO Auto-generated constructor stub
}
I don't know how to populate the table with the column headers as well. This is what I have so far:
DefaultListModel listmodel = new DefaultListModel();
ArrayList<Record> test = new ArrayList<Record>();
DefaultTableModel modelT = new DefaultTableModel();
Object data1[] = new Object[3];
for(int i=0; i<test.size();i++){
data1[0] = test.get(i).Parameter_ID;
data1[1] = test.get(i).NDC_SUM_Claims;
data1[2] = test.get(i).NDC_Claims;
modelT.addRow(data1);
}
table_1 = new JTable(modelT, columnNames);
contentPane.add(table_1, BorderLayout.CENTER);
contentPane.add(table_1.getTableHeader(), BorderLayout.NORTH);
Nothing is outputted. Any help would be great!
Well you need to start by reading the API. You can't program if you don't read the API first.
DefaultTableModel modelT = new DefaultTableModel();
When you read the API what does that constructor do? It creates a model with 0 rows and 0 columns. You will want to create a model with 3 columns and 0 rows so that you can add rows of data to the model. Read the DefaultTableModel API
table_1 = new JTable(modelT, columnNames);
What does that statment do? I don't see a constructor that allows you to specify a model and column names so how does your code compile. You just want to create the table using
the model.
contentPane.add(table_1, BorderLayout.CENTER);
contentPane.add(table_1.getTableHeader(), BorderLayout.NORTH);
The table should be added to the viewport of a JScrollPane. The header will then be displayed as the column header of the scroll pane.
Read the JTable API. The API also has a link to the Swing tutorial on How to Use Tables you need to read for the basics.
ArrayList<Record> test = new ArrayList<Record>();
You create an empty ArrayList. So what do you expect to happen when you iterate through the loop? How can you add data to the model if there is no data in the ArrayList?
Also, did you search the forum/web for examples that use the DefaultTableModel or JTable classes. Those examples will help you write your code.
You can create a custom AbstractTableModel and then create a JTable using that model.
Here is a class handling ArrayList of Arrays:
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
public class DataTableModel<T> extends AbstractTableModel {
/**
* Benjamin Rathelot
*/
private static final long serialVersionUID = -7361470013779016219L;
private ArrayList<T[]> data = new ArrayList<T[]>();
private String[] tableHeaders;
public DataTableModel(ArrayList<T[]> data, String[] headers) {
super();
this.data = data;
this.tableHeaders = headers;
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
if(data.size()>0) return data.get(0).length;
return 0;
}
#Override
public Object getValueAt(int arg0, int arg1) {
// TODO Auto-generated method stub
if(data.size()>=arg0) {
if(data.get(arg0).length>=arg1) {
return data.get(arg0)[arg1];
}
}
return null;
}
#Override
public String getColumnName(int columnIndex) {
return tableHeaders[columnIndex];
}
}

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.

How To Display a ArrayList that Contains a another ArrayList In Jtable with A tableModel

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 !!

jTable still sorts numbers incorrectly after overriding getColumnClass method

I am trying to make my jTable sort numbers but it still does not work. I am not sure what I am doing wrong, but everything seems alright.
My code:
public static javax.swing.JTable jTable1;
public void fillMain() {
jTable1 = new javax.swing.JTable();
//finalcolumns is a List<String> of all my column names
//types is List<Class> of classes of my columns
DefaultTableModel tm = new DefaultTableModel(new Object[0][], new String[] {"testcolumn1", "testcolumn2", "testcolumn3"}) {
#Override
public Class<?> getColumnClass(int col) {
System.out.println("Class: " types.get(col).toString());
//here it really returns the right column class (Integer.class)
return types.get(col);
}
#Override
public int getColumnCount() {
return finalcolumns.size();
}
#Override
public String getColumnName(int col) {
return finalcolumns.get(col);
}
};
jTable1.setModel(tm);
jTable1.setAutoCreateRowSorter(true);
}
As I tagged inside the code, I am Overriding DefaultTableModel methods and the overriding works as it should, all methods that I Override returns proper values.
So it is like: TableModel says: "this column is Integer class and it contains integer objects so I sort it like a String".
Why it happens ?
You are approaching the problem correctly, but I suspect there may be an issue with the way you are initializing the table or with the finalColumns or types lists that are not shown.
A generalized way to implement getColumnClass is shown below. This is based on the suggested implementation presented in the Java Tutorials, but with an added check to protect against a table model with 0 rows:
#Override
public Class<?> getColumnClass(int col) {
Class retVal = Object.class;
if(getRowCount() > 0)
retVal = getValueAt(0, col).getClass();
return retVal;
}
If you replace your tm TableModel declaration/initialization with this snippet below, it should provide the behavior you seek. You should just need to change how it populates the table data and columnHeaders.
Object[][] data = new Object[5][3];
data[0][0] = "word";
data[1][0] = "jive";
data[2][0] = "stuff";
data[3][0] = "word2";
data[4][0] = "abc";
data[0][1] = new Integer(410);
data[1][1] = new Integer(45);
data[2][1] = new Integer(456456);
data[3][1] = new Integer(4);
data[4][1] = new Integer(4);
String[] columnNames = new String[] {"testcolumn1", "testcolumn2"};
DefaultTableModel tm2 = new DefaultTableModel(data, columnNames) {
#Override
public Class<?> getColumnClass(int col) {
Class retVal = Object.class;
if(getRowCount() > 0)
retVal = getValueAt(0, col).getClass();
return retVal;
}
};
Hope this helps.

Updating a JTable from query

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().

Categories

Resources