i've created a swing jtable with some data from a database. in web apps, usually i display the data to the user and set it's unique database id in as an html tag attribute, so that when the user clicks on say edit, i pick the element's hidden db unique id from the html tag attribute using javascript. That way, i know which data user wants to edit and i can update it in the database using it's unique primary key.
Now how do i do this in a desktop app writen in java using swing.
Put it more clearly, am looking for an equivalent of;
<table>
<tr id=1 ><td>david</td></tr>
<tr id=2 ><td>peter</td></tr>
<tr id=3 ><td>Timothy</td></tr>
</table>
Hope am clear. Thanks
Your TableModel which backs up the JTable can contain anything you like. It can for example contain objects like
class User{
public final int ID;
public String name;
public int age;
}
and you can then choose to only include certain values in your JTable
class MyTableModel implements TableModel{
private List<User> users;
#Override
public Object getValueAt(int row, int column){
if ( column == 0 ){
return users.get( row ).name;
}
}
}
But since your TableModel still contains the full User objects, you have all the required information.
Note: the above code will not compile due to missing methods, ... . It is just here to illustrate what I mean
The equivalent is an AbstractTableModel subclass instance backed by a List<YourObject>. When you edit a row, you get the index of the selected row from the table (JTable.getSelectedRow()), then you convert this row index to a model row index (JTable. convertRowIndexToModel()), then you ask your model for the YourObject at this row, and you get the ID of YourObject directly from the object.
Read the JTable tutorial for more details.
public class UserTableModel extends AbstractTableModel {
private List<User> users;
public UserTableModel(List<User> users) {
this.users = new ArrayList<User>(users);
}
#Override
public int getRowCount() {
return users.size();
}
#Override
public int getColumnCount() {
return 1;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return users.get(rowIndex).getName();
}
else {
throw new IllegalArgumentException();
}
}
#Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) {
return String.class;
}
else {
throw new IllegalArgumentException();
}
}
public User getUserAtRow(int rowIndex) {
return users.get(rowIndex);
}
}
Related
I have a swing application where I mainly have a Jtree and a JTable. when the app starts, the tree shows a list of values and the table only displays its column names.Once a node is selected from the tree, some data related to the selected node needs to be displayed in the table.
I have a Table model class which extends the AbstractTableModel as below
import javax.swing.table.AbstractTableModel;
import java.util.List;
public class PropertiesTableModel extends AbstractTableModel{
private List<Field> fieldList;
private final static String[] columnNames= new String[]{"Field","Value"};
public PropertiesTableModel(List<Field> list){
this.fieldList=list;
}
#Override
public String getColumnName(int columnIndex){
return columnNames[columnIndex];
}
#Override
public int getRowCount() {
return fieldList.size();
}
#Override
public int getColumnCount() {
return 2;
}
//this method is called to set the value of each cell
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Field field= (Field) fieldList.get(rowIndex);
switch(columnIndex){
case 0:
return field.getFieldDef().getfName();
case 1:
return field.getDefaultValue();
}
return null;
}
#Override
public Class<?> getColumnClass(int columnIndex){
switch (columnIndex){
case 0:
return String.class;
case 1:
return Object.class;
}
return null;
}
}
from another class I use this table model as below
public void populateTableData(List<Field> list){
this.fieldList=list;
JTable propertiesTable=new JTable();
propertiesTable.setModel(new PropertiesTableModel(fieldList));
}
When I run the application and select a node from the tree, the table is not getting populated with expected data. I made sure that the fieldList data is passed to the TableModel but only the getColumnName() and the getColumnCount() methods are getting called.
I want to know if something is missing in my code.
Probably you forgot to include the fact that you need to trigger the view (JTable) to update itself from your Model if the underlying data changes in the Model (using fireTableDataChanged)... I assume that initially your list is empty and data gets added to the list and that dats is not displayed in the JTable.
I can recommend you to have a look at GlazedLists !!! (http://www.glazedlists.com/)
This freeware library suits your needs perfectly !
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 !!
im developing an application and i'm trying to insert a new row into jtable
i've followed this tutorial , the user can add/remove product information(row) through a form.the database & the table should be updated ,the remove function works well but i can't insert new row into the table .
Note:- when i close the app & run it again the table is updated
and here's my code
public class TableModel extends AbstractTableModel {
Object[] values;
String[] columnNames;
private ArrayList productInfoList;
public TableModel() {
super();
Session session = HibernateUtil.openSession();
Query q = session.createQuery("from Product");
productInfoList = new ArrayList(q.list());
session.close();
}
#Override
public int getRowCount() {
//return dataVec.size();
return productInfoList.size();
}
#Override
public int getColumnCount() {
return 9;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Product product = (Product) productInfoList.get(rowIndex);
values = new Object[]{product.getProdectId(),
product.getProductName(), product.getProductBuyingPrice(),
product.getProductSalesPrice(), product.getCategory(), product.getBrand(),
product.getProductQuantity(), product.getProductMinQuantity(), product.getProductDescription()};
return values[columnIndex];
}
#Override
public String getColumnName(int column)
{
columnNames=new String[]{"id","Product Name","Buy price","Sale price ","Category",
"Brand","Quantatity","Min Quantatity","Description"};
return columnNames[column];
}
public void removeRow(int rowIndex) {
productInfoList.remove(rowIndex);
fireTableRowsDeleted(rowIndex, rowIndex);
}
public void insertRow(int rowIndex,Product everyRow) {
productInfoList.add(rowIndex, everyRow);
fireTableRowsInserted(rowIndex, rowIndex);
}
}
this is the code that i try to insert row with
public void AddRow() {
int position = jTable1.getRowCount() - 1;
System.out.println(position); // test
Product product = new Product();
tablemodel.insertRow(position, product);
}
Please help me as i'm get tired of it :|
Your TableModel is storing a Product object in an ArrayList.
So, when you want to add a new row to the model you need to create a new Product object and add the Product to the ArrayList.
Also, you don't need to invoke table.repaint(), the insertRow(...) method is invoking the fireTableRowsInserted(...) method which will tell the table to repaint the row.
I have a JTable that loads data from a database and then generates a summary row at the bottom of the table. I want the user to be able to sort the table, but I'd like the summary row to always remain at the bottom of the table.
I've been trying to create a custom TableRowSorter, but I'm having some trouble figuring it out and getting it to do what I want.
Anyone know how to do this?
Thanks
You need a class which holds whether the value is a summary or not.
Something like this
public class SummarizedValue {
public Integer value;
public boolean summarized;
public String toString() {
return null == value? "" : value.toString();
}
}
public class SummaryComparator implements Comparator<SummarizedValue> {
public int compare(SummarizedValue v1, SummarizedValue v2) {
if (v1.summarized) return 1;
if (v2.summarized) return -1;
return v1.value.compareTo(v2.value);
}
}
public class SummaryBackComparator implements Comparator<SummarizedValue> {
public int compare(SummarizedValue v1, SummarizedValue v2) {
if (v1.summarized) return 1;
if (v2.summarized) return -1;
return v2.value.compareTo(v1.value);
}
}
You need to display the objects of class SummarizedValue in your column and your row sorter should return SummaryComparator. Also your need to override toggle behaviour in RowSorter to use SummaryBackComparator.
I have a sample code that we use to dynamic row numbers in Java Swing Table i.e JTable. I new to JavaFX and would like to the same in JavaFX. Is there is any way to set automatic row numbers in JavaFX Table
class LineNumberTable extends JTable {
private JTable mainTable;
public LineNumberTable(JTable table) {
super();
mainTable = table;
setAutoCreateColumnsFromModel(false);
setModel(mainTable.getModel());
setAutoscrolls(false);
addColumn(new TableColumn());
getColumnModel().getColumn(0).setCellRenderer(mainTable.getTableHeader().getDefaultRenderer());
getColumnModel().getColumn(0).setPreferredWidth(40);
setPreferredScrollableViewportSize(getPreferredSize());
}
#Override
public boolean isCellEditable(int row, int col) {
if (col == uneditableColumn) {
return false;
}
return bEdit;
}
#Override
public Object getValueAt(int row, int column) {
return Integer.valueOf(row + 1);
}
#Override
public int getRowHeight(int row) {
return mainTable.getRowHeight();
}
}
In JavaFX, you use TableColumns with CellFactories and CellValueFactories to populate your TableView.
The JavaFX tutorials have an article that might get you started.
In one approach I have used I convert the business objects to display into presentation objects and add all necessary properties (like in your case, the number) to them.
EDIT: In a second, cleaner approach, you could set your CellFactory to create a TableCell that shows its own index property in TableCell#updateItem(S, boolean):
public class NumberedCell extends TableCell{
protected void updateItem(Object object, boolean selected){
setText(String.valueOf(getIndex());
}
}