This is driving me crazy. I read the Sun's tutorial regarding the creation of a basic table with a default data model, but cant figure out a simple example about how to load an array of data-objects like:
class dataObject{
String name;
String gender;
Byte age;
public dataObject (String name, String gender, Byte age){
this.name = name;
.
.
}
Then i create, for example, a vector of this stuff:
Vector v = new Vector(99);
v.addElement(new dataObject("Marrie", "Female", 33);
v.addElement(new dataObject("John", "Male", 32);
With dataObject i'd gather the info, now how the heck i show it in a table? Because this is not working:
JTable newTable = new Jtable(v, header) // header is another Vector.
I'm getting some errors that lead me to this last line. So, any help, even little, is apreciated. I know there are several threads about this, but those people already have a gasp about how JTable + TableModel works, I just barely get it.
Thanks a lot.
There are two ways you can create a JTable with a basic, prepared dataset:
a 2D Object array
a Vector whose elements are Vector
so you can do this:
Object [][] model = {{"Marrie", "Female","33"},{"John","Male","32"}};
JTable table = new JTable(model);
or you could do this:
Vector model = new Vector();
Vector row = new Vector();
row.add("Marrie");
row.add("Female");
row.add("33");
model.add(row);
row = new Vector();
row.add("John");
row.add("Male");
row.add("32");
model.add(row);
JTable table = new JTable(model);
The next step would be to implement your own TableModel to utilize the DataObject class that you have put together (note that Java classes start with caps). Extending AbstractTableModel makes life easy, as you only need to implement three methods to get started:
public int getRowCount();
public int getColumnCount();
public Object getValueAt(int row, int column);
the first two are easy, you can get the size of your Vector for row count and hard-code the val for column count. getValueAt is where you pull the data from your DataObject
Here is an example using an anonymous class, extending AbstractTableModel.
final Vector<DataObject> myDataObjects = new Vector<DataObject>();
myDataObjects.add(...);// add your objects
JTable table = new JTable(new AbstractTableModel() {
public int getRowCount() {return myDataObjects.size();}
public int getColumnCount() { return 3; }
public Object getValueAt(int row, int column){
switch (column) {
case 0:
return myDataObjects.get(row).getName();
case 1:
return myDataObjects.get(row).getGender();
case 2:
return myDataObjects.get(row).getAge();
default:
return "";
}
}
});
I have kept the Vector so as to keep it close to your current implementation. You can easily change that to an ArrayList in this example without any worries.
The problem is, the constructor you're using was designed to hold a vector which holds other vectors.
Each one with the information.
See this working sample to understand it better:
import javax.swing.*;
import java.util.Vector;
public class TableDemo {
public static void main( String [] args ){
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
Vector<Object> row = new Vector<Object>();
row.add( "Marie");
row.add( "Female");
row.add( 33);
data.add(row);
Vector<Object> otherRow = new Vector<Object>();
otherRow.add( "John");
otherRow.add( "Male");
otherRow.add( 32 );
data.add(otherRow);
Vector<String> headers = new Vector<String>();
headers.add("Name");
headers.add("Gender");
headers.add( "Age");
JTable table = new JTable( data, headers );
JFrame frame = new JFrame();
frame.add( new JScrollPane( table ));
frame.pack();
frame.setVisible( true );
}
}
Which creates:
something like this http://img695.imageshack.us/img695/2032/capturadepantalla201006r.png
Just in case, you should take a look at this:
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
If you haven't done yet.
You can't load data objects into the DefaultTableModel. You need to create a custom TableModel to do this. The Bean Table Model is such a model that can make this process easier for you.
I've never used JTable before, but the documentation says that the constructor takes a "Vector of Vectors" as the first parameter, and not a Vector of dataObjects.
I know a lot of people can be wary of including yet another jar file, but to be honest, no matter how simple the JTable (or JList or JComboBox), I always utilise the GlazedLists library. Quite frankly it's one of the most amazing libs you'll ever use. It's very, very flexible. But a simple example consists of putting your beans into a special list called EventList. Then construct a table format; create the model by binding the format to the data list, and then set as the table's model.
Assume you have a Person class:
public class Person {
private String firstName;
private String surname;
private int age;
... standard constructors, getters and setters...
}
Now, to make your table display a list of these people:
EventList<Person> peopleEventList = new BasicEventList<Person>();
peopleEventList.add(... create some objects and add it the usual way ...);
...
String[] columnProperties = { "firstName", "surname", "age" };
String[] columnLabels = { "First name", "Surname", "Age" };
TableFormat personTableFormat = GlazedLists.tableFormat(columnProperties, columnLabels);
EventTableModel personTableModel = new EventTableModel(peopleEventList, personTableFormat);
myJTable.setModel(personTableModel);
I'm writing this from memory, but I think it's more or less correct. The great thing with using this library is it's seriously easy to add sorting and filtering to the table. Get the basic table working first, then start looking on the GlazedLists site to see what else you can do. There are some really good screencasts too.
PS I'm in no way affiliated with this library, I simply think it rocks!
Related
I have a jTable in netbeans that is abstract and contains several columns like code, name, location, gravity, etc. I already have the code for this part, but I want to sort only a few columns such as name and severity. I do not know if anyone can help me, I will leave below the part of code I have to order the table.
public void sort() {
TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<DefaultTableModel>(modeloTabela);
tabelaDoentes.setRowSorter(sorter);
sort();
}
I have a C# background and I'm pretty new to Java. Trying to port my windows application to Mac using Java.
The issue I have is how to bind a HashTable that contains a class to a JTable so that the variables in the key show up in the JTable. In C# WPF it's very easy, just binding GridView.ItemSource to dictionary.keys. But in Java it seems much more complicated. Here is what I have so far:
Map<Files, String> files = new HashMap<Files,String>();
public class Files {
public Files(String files, String duration, String status) {}
}
public void AddFiles(String addfile, String addduration, String addstatus, String path){
files.put(new Files(
addfile, addduration, addstatus),
path);
}
In C# the class would look a little different, but I can just do GridView.Itemsource = files.Keys and voila, it all shows upp perfectly. How can I achieve something similar in Java?
I know that JTable can use a multidimensional array to load the values, so I am right now trying to load the values of HashTable into Object[][] tableData and then use:
String[] columnNames = {"File","Duration", "Status"};
final JTable table = new JTable(tableData, columnNames);
The problem is that I don't know how to access the variables inside the class "Files" inside the HashMap "files".
I know there is: .getKey().getClass() but I still haven't been able to load the multidimensional array with the values of the class "Files" inside the HashMap.
Create a tableModel extending from the base class AbstractTableModel. In here you'll have to override the appropriate methods (your IDE will point them out), the most important one being getValueAt().
Override this one in a fashion similar to:
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return data.get(rowIndex).getValueX; // Change to however you'd like to call a single value from your map
case 1:
return data.get(rowIndex).getValueY;
case 2:
return data.get(rowIndex).getValueZ;
default:
throw new IndexOutOfBoundsException();
}
}
You can call your model with your data as a parameter. Afterwards, use this model as an argument to your JTable and you should be fine.
You can get the keys of a HashMap using HashMap.keySet() method.
This will return a Set of the key objects, which you have stored in your HashMap.
HashMap<Files, String> yourHashMap = new HashMap<Files, String>();
Set<Files> keys = yourHashMap.keySet();
Once you have got the set, assuming that you have the DefaultTableModel set to your JTable, you can do,
for(Files f : keys) {
yourDefaultTableModel.addRow(new String[]{f.files, f.duration, f.status});
}
NOTE:
Its always better to use a class which overrides equals() method & which is immutable to use as HashMap key.
Overriding equals() will avoid keys being overwritten incase of Hash collision, and making a class immutable doesn't make the value associated with the key orphan (since the key will not change once its created)
So I suggest using HashMap<String, Files> instead of HashMap<Files,String> if you feel making Files class immutable breaks its purpose.
This is driving me crazy. I read the Sun's tutorial regarding the creation of a basic table with a default data model, but cant figure out a simple example about how to load an array of data-objects like:
class dataObject{
String name;
String gender;
Byte age;
public dataObject (String name, String gender, Byte age){
this.name = name;
.
.
}
Then i create, for example, a vector of this stuff:
Vector v = new Vector(99);
v.addElement(new dataObject("Marrie", "Female", 33);
v.addElement(new dataObject("John", "Male", 32);
With dataObject i'd gather the info, now how the heck i show it in a table? Because this is not working:
JTable newTable = new Jtable(v, header) // header is another Vector.
I'm getting some errors that lead me to this last line. So, any help, even little, is apreciated. I know there are several threads about this, but those people already have a gasp about how JTable + TableModel works, I just barely get it.
Thanks a lot.
There are two ways you can create a JTable with a basic, prepared dataset:
a 2D Object array
a Vector whose elements are Vector
so you can do this:
Object [][] model = {{"Marrie", "Female","33"},{"John","Male","32"}};
JTable table = new JTable(model);
or you could do this:
Vector model = new Vector();
Vector row = new Vector();
row.add("Marrie");
row.add("Female");
row.add("33");
model.add(row);
row = new Vector();
row.add("John");
row.add("Male");
row.add("32");
model.add(row);
JTable table = new JTable(model);
The next step would be to implement your own TableModel to utilize the DataObject class that you have put together (note that Java classes start with caps). Extending AbstractTableModel makes life easy, as you only need to implement three methods to get started:
public int getRowCount();
public int getColumnCount();
public Object getValueAt(int row, int column);
the first two are easy, you can get the size of your Vector for row count and hard-code the val for column count. getValueAt is where you pull the data from your DataObject
Here is an example using an anonymous class, extending AbstractTableModel.
final Vector<DataObject> myDataObjects = new Vector<DataObject>();
myDataObjects.add(...);// add your objects
JTable table = new JTable(new AbstractTableModel() {
public int getRowCount() {return myDataObjects.size();}
public int getColumnCount() { return 3; }
public Object getValueAt(int row, int column){
switch (column) {
case 0:
return myDataObjects.get(row).getName();
case 1:
return myDataObjects.get(row).getGender();
case 2:
return myDataObjects.get(row).getAge();
default:
return "";
}
}
});
I have kept the Vector so as to keep it close to your current implementation. You can easily change that to an ArrayList in this example without any worries.
The problem is, the constructor you're using was designed to hold a vector which holds other vectors.
Each one with the information.
See this working sample to understand it better:
import javax.swing.*;
import java.util.Vector;
public class TableDemo {
public static void main( String [] args ){
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
Vector<Object> row = new Vector<Object>();
row.add( "Marie");
row.add( "Female");
row.add( 33);
data.add(row);
Vector<Object> otherRow = new Vector<Object>();
otherRow.add( "John");
otherRow.add( "Male");
otherRow.add( 32 );
data.add(otherRow);
Vector<String> headers = new Vector<String>();
headers.add("Name");
headers.add("Gender");
headers.add( "Age");
JTable table = new JTable( data, headers );
JFrame frame = new JFrame();
frame.add( new JScrollPane( table ));
frame.pack();
frame.setVisible( true );
}
}
Which creates:
something like this http://img695.imageshack.us/img695/2032/capturadepantalla201006r.png
Just in case, you should take a look at this:
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
If you haven't done yet.
You can't load data objects into the DefaultTableModel. You need to create a custom TableModel to do this. The Bean Table Model is such a model that can make this process easier for you.
I've never used JTable before, but the documentation says that the constructor takes a "Vector of Vectors" as the first parameter, and not a Vector of dataObjects.
I know a lot of people can be wary of including yet another jar file, but to be honest, no matter how simple the JTable (or JList or JComboBox), I always utilise the GlazedLists library. Quite frankly it's one of the most amazing libs you'll ever use. It's very, very flexible. But a simple example consists of putting your beans into a special list called EventList. Then construct a table format; create the model by binding the format to the data list, and then set as the table's model.
Assume you have a Person class:
public class Person {
private String firstName;
private String surname;
private int age;
... standard constructors, getters and setters...
}
Now, to make your table display a list of these people:
EventList<Person> peopleEventList = new BasicEventList<Person>();
peopleEventList.add(... create some objects and add it the usual way ...);
...
String[] columnProperties = { "firstName", "surname", "age" };
String[] columnLabels = { "First name", "Surname", "Age" };
TableFormat personTableFormat = GlazedLists.tableFormat(columnProperties, columnLabels);
EventTableModel personTableModel = new EventTableModel(peopleEventList, personTableFormat);
myJTable.setModel(personTableModel);
I'm writing this from memory, but I think it's more or less correct. The great thing with using this library is it's seriously easy to add sorting and filtering to the table. Get the basic table working first, then start looking on the GlazedLists site to see what else you can do. There are some really good screencasts too.
PS I'm in no way affiliated with this library, I simply think it rocks!
I'm working on a Swing based project that will display large amounts of data using a Table component. I'm trying to decide what are the best alternatives in terms of efficiency and management of the parsed data. The master table can be manipulated (i.e. views of the complete data can be created, or removed),so the complete data needs to be hold in memory
I know these kind of problems can have many different solutions. I thought of creating a class representing one entry on the log, with properties representing each 'property' on it. I can possible use Comparator objects to sort based on these fields, and use these objects to build a table component.
This might not be a good idea if the total number of entries is in the order of 5000-10000 lines
Any suggestion on good practices to manage this kind of data and perform manipulations to it to render a graphic component are received.
Not many details have been provided, so I'm basically looking for general ideas on how to approach the problem.
I'm presuming that the files are all parsed and an in memory representation of parsed data
is available when the table is displayed. You need to have your own tablemodel which gets data from the parsed files.
Something like below can be your table model:
class MyTableModel extends AbstractTableModel {
private final List<String> columnNames;
private List<RowData> rows;
MyTableModel() {
columnNames = new ArrayList<String>();
columnNames.add("Name");
//...
rows = new ArrayList<RowData>();
}
// populate the table data model with a List
// that contains parsed data, each list element
// could correspond to a record or line (say)
void setCoreData(final List<RowData> data) {
this.rows = data;
}
public Object getValueAt(final int pRow, final int pCol) {
if (getColumnName(pCol).equals("Name")) {
return rows.get(pRow).getName();
}
//... .
}
// corresponds to the rows of table instances of which
// are created by output of parsing
private class RowData {
private String name;
public Object getName() {
return name;
}
}
// table instantitaion can be as below (say)
JTable myTable = new JTable(new MyTableModel());
I would like to have a JFrame window with an initial empty table of say, 10 columns. An action event generated by a mouse click should then populate the table with a list of 10 or less items, the leaving the used rows of the table empty. How should this be done?
I'd recommend defining your own TableModel implementation by subclassing AbstractTableModel. That way you can "back" your model with any suitable collection (e.g. java.util.List). When an ActionEvent is fired you would typically amend your underlying collection and then fire a TableModelEvent to cause the JTable to be repainted.
For this, you should create a DefaultTableModel with the data you want, and for the blank lines, you fill the object table with null values.
It´s simpler with some code:
As I don't know where you data come from, I'll presume it come from a matrix with less than 10 rows:
String data[][] = {{"a","b"}, {"c","d"}};
you have to create a new matrix with your previous data and the null cells for completion of the table. In the end You'll have something like this.
Object data2[][] = {{"a","b"},
{"c","d"},
{null,null},
{null,null},
{null,null},
{null,null},
{null,null},
{null,null},
{null,null},
{null,null}};
This way you'll have a 10x2 matrix that will fill your table. Now you can update your DefaultTableModel
yourTable.setModel(
new DefaultTableModel(data2, new String [] {"Column1Title", "Cloumn2Title"}) {
Class[] types = new Class[] {String.class,String.class};
boolean[] canEdit = new boolean[] {true, true};
#Override
public Class getColumnClass(int columnIndex){ return types [columnIndex];}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex){ return canEdit [columnIndex];}
});
And that's it. I presume you don't have problems to create your Object matrix.
Besides creating your own TableModel as explained by Adamski, you can use the javax.swing.table.DefaultTableModel directly.
It has a constructor which takes the number of columns and rows as argument and methods to manage the data (addRow, insertRow, setDataAt, ...).
I would prefer creating an own TableModel, unless it's for a very simple program/functionality.