Automatic row numbering in javafx table - java

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());
}
}

Related

How to change value of a cell in a table model in Java?

I created a class inheriting from AbstractTableModel. I want to override setValueAt(), so that it will change the value of the cell in row r and column c into the multidimensional array v. But I keep getting errors.
public class ItemListTableModel extends AbstractTableModel{
public void setValueAt(Object v, int r, int c) {
rowData[r][c] = v;// This is where the error is.
fireTableCellUpdated(r, c);
}
#Override
public int getRowCount() {
}
#Override
public int getColumnCount() {
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
}
public boolean isCellEditable(int row, int col){
return true;
}
}
AbstractTableModel has no concept of the content of the model or how it's managed, that's kind of the point. It's designed to allow developers to design their own models based on their own complex requirements.
A simpler solution would be to use a DefaultTableModel, which provides all the functionality out of the box...
DefaultTableModel model = new DefaultTableModel(rows, columns); // you need to define rows and columns for yourself
model.setValueAt(row, column, value); // Again, you need to define the variables for your self
Should you "absolutely" need a custom table model based on AbstractTableModel, then you will need to provide the storage mechanisms which are used to store data within a given row/data yourself.
Typically, I define a POJO which represents the row and then add these to some kind of List, as it provides a simple mechanism for growing and shrinking the model
In your class you haven't declared the type of rowData. Presumably it's an 2 x 2 int array, but you haven't declared it, so the compiler cannot find the identifier. What you want to do is first declare rowData like
int[][] rowData = new int[r][v];
Then you can assign v to rowData as normal.
Example use of AbstractTableModel::setValueAt().
class MyTableModel extends AbstractTableModel {
private final String[] columnNames = new String[]{"Col One", "Col Two"};
private final Object[][] data = new String[][]{new String[]{"R1C1", "R1C2"}, new String[]{"R2C1", "R2C2"}};
#Override
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
......
rest of the code

java jTable : how to know the row number?

I wrote a class that implements TableCellRenderer, since I want to put checkboxes inside the jTable.
In the getTableCellRendererComponent method of this class, i have the condition :
if(isSelected){ do ..... }
inside this if condition, how can I know the row number ?
code :
private static class ValueRenderer extends JCheckBox
implements TableCellRenderer {
private static final Color hilite = new Color(0xE8E8E8);
public ValueRenderer() {
this.setOpaque(true);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,boolean hasFocus, int row, int col) {
Value v = (Value) value;
this.setSelected(v.selected);
if(isSelected)
{
if(v.selected==true)
System.out.println("checked");
else System.out.println("unchecked");
}
return this;
}
}
private static class Value {
private Boolean selected;
public Value(Boolean selected) {
this.selected = selected;
}
}
Why are you creating a Value class and a custom renderer? From the code it is just a Boolean. Just add the Boolean directly to the TableModel and then override the getColumnClass() method of the JTable or TableModel to return Boolean and the table will use the default Boolean renderer.
Read the JTable API and follow the link to the Swing tutorial on How to Use Tables for an example that uses Booleans.
Use the row parameter passed to your renderer. It's zero based just like arrays in Java.

How to render a checkbox?

I'm using Glazed lists, in a jTable where I have a column which is boolean.
By default the jTable renders a checkbox where the column is type Boolean.Class.
Using Glazed lists i cannot get the checkbox which is needed. I rendered checkboxs extending the DefaultTableCellRenderer but i'm not satisfied with it because the checkboxs are not "clickable".
In the GL faq http://www.glazedlists.com/documentation/faq i found:
*Q: How do I specify that my boolean table cells be rendered with a checkbox?
For some reason, Glazed Lists has no getColumnClass() method.
A: If you need to specify the column class, you need to implement the AdvancedTableFormat interface instead of the regular TableFormat class.
If you are using the GlazedLists.tableFormat() factory method, you must specify the base Object's class for a proper implementation of the AdvancedTableFormat.getColumnClass() method.*
Does some of you have experience with this I did not find any links with an example. The essential link in the faq is broken.
I tried with this:
public class CheckBoxTableModel implements AdvancedTableFormat {
public Class getColumnClass(int column) {
if(column==4)
return Boolean.class;
else
return Object.class;
}
}
Please help!
EDIT:
I tried with this, the form with the jtable does not show
private class TicketTableFormat implements AdvancedTableFormat<Ticket> {
private final String[] cols = new String[]{"Id", "From", "Subject", "Date", "Incomplete"};
public int getColumnCount() {
return cols.length;
}
public String getColumnName(int colId) {
return cols[colId];
}
public Class getColumnClass(int col) {
if (col == 4) {
return Boolean.class;
} else {
return Object.class;
}
}
public Object getColumnValue(Ticket ticket, int colId) {
switch (colId) {
case 0:
return ticket.getId();
case 1:
return ticket.getFrom();
case 2:
return ticket.getSubject();
case 3:
return ticket.getDate();
case 4:
return ticket.getIncomplete();
}
return null;
}
public boolean isEditable(Ticket e, int col) {
if (col < 4) {
return false;
} else {
return true;
}
}
public Ticket setColumnValue(Ticket e, Object o, int i) {
e.setB((Boolean) editedValue);
return e;
}
public Comparator getColumnComparator(int i) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
i call it with this:
TicketTableFormat tbFormat = new TicketTableFormat();
TicketsModel = new EventTableModel(textFilteredTickets, tbFormat);
ticketTable.setModel(TicketsModel);
The basic point here is that rendering table cells and eiting them are two different things. For table cell rendering, the renderer only serves as a 'stamp', i.e. the check box is initialized to the state that should be rendered and aterwards the Table only takes apicture of the renderer (by invoking its paint method) and places the tat picture in the appropriate cell - for rendering all the cells, the same instance of checkbox is re-configured over and over again to represent the according cell value. What you did in your code, is specifying the data type flavor of the model, so that the default table cell renderer chosen by the table is a checkbox renderer.
For the checkbox to be editable, a cell editor must be attached to the table cell (e.g. by configuring an editor for the particular column). In case a table cell receives input focus, the table cell editor component is initialized and placed inside the table cell (i.e. above the image that was painted by the renderer before). This cell editor component (would be a checkbox in your case) is remainig there (accepting user input via mouse or keyboard) until the user navigates away from that particzular table call. In the moment when editing ends, the cell editor is asked for the vale it has captured from the editing process, (i.e. getCellEditorValue() is called on the editor) and hte value is taken by the table and written back to the table model for that cell.
So in short: The renderer is only stamping data on the cell, i.e. outputting, an editor component is necessary to receive input.
Example code for custom table cell editor
Java tuorial explaining the thing in detail and having also checkbox examples and code
Did you implement isEditable(...) & setColumnValue(...) in your implementation of AdvancedTableFormat?
Implementing the following methods works for me.
public int getColumnCount()
public String getColumnName(int column)
public Object getColumnValue(E model, int column)
public boolean isEditable(E model, int column) // For making the checkbox editable
public IFdsModel setColumnValue(E model, Object value, int column)
public Class getColumnClass(int column) // For making it a Checkbox
public Comparator<E> getColumnComparator(int arg0) // for sorting (if you have a SortedList)
Edit: an example (quick and dirty)
import java.util.Comparator;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.gui.AdvancedTableFormat;
import ca.odell.glazedlists.gui.WritableTableFormat;
import ca.odell.glazedlists.swing.EventTableModel;
public class Tester {
private static class MyBoolean {
private Boolean b = Boolean.FALSE;
public Boolean getB() {
return b;
}
public void setB(Boolean b) {
this.b = b;
}
}
private static class BooleanTableFormat implements AdvancedTableFormat<MyBoolean>, WritableTableFormat<MyBoolean> {
#Override
public int getColumnCount() {
return 1;
}
#Override
public String getColumnName(int column) {
return "Bool";
}
#Override
public Object getColumnValue(MyBoolean baseObject, int column) {
return baseObject.getB();
}
#Override
public Class getColumnClass(int column) {
return Boolean.class;
}
#Override
public Comparator getColumnComparator(int column) {
throw new IllegalStateException("Not yet implemented.");
}
#Override
public boolean isEditable(MyBoolean baseObject, int column) {
return true;
}
#Override
public MyBoolean setColumnValue(MyBoolean baseObject, Object editedValue, int column) {
baseObject.setB((Boolean) editedValue);
return baseObject;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
EventList<MyBoolean> list = new BasicEventList<MyBoolean>();
list.add(new MyBoolean());
list.add(new MyBoolean());
EventTableModel<MyBoolean> etm = new EventTableModel<MyBoolean>(list, new BooleanTableFormat());
JTable table = new JTable(etm);
JFrame f = new JFrame("Tester");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 200);
f.getContentPane().add(new JScrollPane(table));
f.setVisible(true);
}
});
}
}

Update Table GUI that extends custom AbstractTableModel

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.

Correctly getting data from a (sorted) JTable

I have developed a basic custom JTableModel as follows
public class CustomTableModel extends DefaultTableModel {
List<MyClass> data;
public CustomTableModel(List<MyClass> data) {
this.data = data;
}
public Class<?> getColumnClass(int columnIndex) {
return MyClass.class;
}
public MyClass getValueAt(int rowIndex, int columnIndex) {
return data.get(rowIndex);
}
// ...
}
I then use a basic custom JTableCellRenderer as follows
public class CustomTableCellRenderer extends JLabel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
MyClass myClass = (MyClass)value;
lbl.setText(myClass.getString());
return this;
}
}
I also have a custom JPanel that displays various information as follows
public class MyPanel extends JPanel {
private MyClass myClass;
public MyPanel(MyClass myClass) {
// initialize components
}
public setMyClass(MyClass myClass) {
this.myClass = myClass;
updateFields();
}
private void updateFields() {
this.fieldString.setText(myClass == null ? "" : myClass.getString());
// ...
}
}
Finally, I use a table to list my data and the custom panel to display the details of the selected data.
public class JCustomFrame extends JFrame {
public JCustomFrame(List<MyClass> data) {
// ...
JTable table = new JTable(new CustomTableModel(data));
table.setDefaultRenderer(MyClass.class, new CustomTableCellRenderer());
}
}
What I am trying to accomplish is get the selected MyClass from the table regardless of sorting.
I tried ListSelectionListener but the methods do not return anything other than the selected indexes. Even if I have the index, if the table is sorted, my model is not so sophisticated and will return the wrong object.
...Even if I have the index, if the table is sorted, my model is not so sophisticated and will return the wrong object...
You have to use:
JTable.convertRowIndexToModel( int viewIndex )
Maps the index of the row in terms of the view to the underlying TableModel. If the contents of the model are not sorted the model and view indices are the same.
With that index you can access your table model and see what's the object you need.
Note Table sorting along with this method was introduced in Java 1.6

Categories

Resources