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.
Related
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];
}
}
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 want to add data to my own JTable model in runtime. I have the table and add button on my interface. As I understand I cant do it with two dimensional array and want to use Arraylist in my custom made table model but I dont know how to make the constructor if I use such type of data.
static String[] columnNames = {"A", "B", "C"};
static Object data[][] = new Object[15][3];
public MyTableModel() {
super(data, columnNames);
}
this is the constructor for data as two dimansional array but I want to use:
ArrayList<Object[]> data = new ArrayList<Object[]>();
How to make it
One way to do it, is to use AbstractTableModel. Here is an example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
public class TestTable {
public static class MyModel extends AbstractTableModel {
private List<Object[]> data;
private List<String> columnNames;
public MyModel(List<String> columnNames, List<Object[]> data) {
super();
this.columnNames = columnNames;
this.data = data;
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return columnNames.size();
}
#Override
public String getColumnName(int column) {
return columnNames.get(column);
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data.get(rowIndex)[columnIndex];
}
}
protected void initUI() {
JFrame frame = new JFrame(TestTable.class.getSimpleName());
List<String> columns = Arrays.asList("Name", "Age");
List<Object[]> data = new ArrayList<Object[]>();
for (int i = 0; i < 50; i++) {
Object[] value = new Object[2];
value[0] = "Name-" + i;
value[1] = 12 + i;
data.add(value);
}
JTable table = new JTable(new MyModel(columns, data));
frame.add(new JScrollPane(table));
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestTable().initUI();
}
});
}
}
If you need to to modify your data List<Object[]>, don't forget to fire appropriate Table Events. AbstractTableModel contains them all already.
It's a bit hard to tell what you're doing as you haven't included the full source code of your table model, so I'm going to make a few assumptions here.
You're probably either extending AbstractTableModel or DefaultTableModel. In either case, you shouldn't have to add your data to the model via the constructor. Instead, you will want to override the following methods in your TableModel extension:
getRowCount()
getColumnCount()
getValueAt(int row, int column)
Make it so that each of these methods indexes into your ArrayList<Object[]> data object - e.g., getValueAt(row,column) should return something like data.get(row)[column]. Then add your TableModel to a JTable and you should be good to go, as far as displaying the custom data goes.
Now... when your data changes (either you changed the value of a cell in the table or you added/removed rows), you just call fireTableDataChanged() on your TableModel (assuming it has extended AbstractTableModel or one of its subclasses). This will force the UI to update with the changes you made to the underlying data.
The most straightforward way to create your own table model is to inherit from AbstractTableModel. Then override, at a minimum, getRowCount, getColumnCount, and getValueAt.
You can then either create the table using "new JTable(mymodel)", where "mymodel" is an instance of the model you have created, or you could create it with just "new JTable", and then later do setModel to attach your model to the JTable.
For example -- and while I've done this a bazillion times, I'm writing this off the top of my head so no warranties expressed or implied, odds are there's a syntax error or two in there somewhere:
class ArrayListModel extends AbstractTableModel
{
ArrayList<Object[]> list;
public ArrayListModel(ArrayList<Object[]> list)
{
this.list=list;
}
public int getRowCount()
{
return list.size();
}
public int getColumnCount()
{
if (list.size()==0)
{
return 0;
}
else
{
return list.get(0).length;
}
}
public Object getValueat(int row, int column)
{
return list.get(row)[column];
}
}
... somewhere else ...
ArrayListModel mymodel=new ArrayListModel(somedata);
JTable mytable=new JTable(mymodel);
... etc ...
Side note: When I was first learning Java, I thought that the "normal" way to create a JTable was to use the default model, create a vector of vectors or a 2-D array and then populate. I thought creating your own model would be something you did in rare, odd cases. But I've since figured out that the default model is only the best way in rare, simple cases. Now I almost always create my own model: it's usually easier to code and easier to understand. Typically I have an ArrayList of some class that I've created with specific fields, and then in my model class I have something like:
public Object getValueAt(int row, int col)
{
Whatever w=list.get(row);
if (col==0) return w.foo;
else if (col==1) return w.bar;
else if (col==2) return w.plugh;
else throw SomeException();
}
Or use a case statement. Same idea.
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.