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.
Related
In this code, I'm adding the data from Database. I want to set cell renderer with a label. But if I run this code I got only check box.
try {
List<Group> listgrChild = grMgmtModel.performList();
for (final Group group : listgrChild) {
table.getColumnModel().getColumn(0)
.setCellRenderer(new TableCellRenderer() {
// the method gives the component like whome the
// cell must
// be rendered
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean isFocused,
int row, int col) {
boolean marked = new Boolean(String
.valueOf(value));
JCheckBox rendererComponent = new JCheckBox();
if (marked) {
rendererComponent.setSelected(true);
}
return rendererComponent;
}
});
tbModel.addRow(new Object[] { group.getGroupName() });
}
You comment, "renderComponent.setText("Hello") is giving only last value."
Verify that your TableModel has individual storage for each row's check box state and label value. In this example, the class Value holds the relevant data:
private static class Value implements Comparable<Value> {
private Boolean selected;
private Double value;
…
}
The corresponding TableModel manages a List<Value> and the required renderer and editor use the data from each Value instance accordingly. As an aside, Value implements the Comparable interface for convenience in sorting.
I have a MultilineCellRenderer which should wrap the multiple lines in JTable cell.
public class MultiLineTableCellRenderer
extends JTextArea implements TableCellRenderer {
/**
*
*/
private static final long serialVersionUID = 1L;
public MultiLineTableCellRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
setText(value.toString());//or something in value, like value.getNote()..
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setSize(table.getColumnModel().getColumn(column).getWidth(),
getPreferredSize().height);
if (table.getRowHeight(row) != getPreferredSize().height) {
table.setRowHeight(row, getPreferredSize().height);
}
return this;
}
}
I am creating and assigning this cell renderer as default cell renderer for myjtable(cnr_DATA)
MultiLineTableCellRenderer r = new MultiLineTableCellRenderer();
cnr_DATA.setDefaultRenderer(String.class, r);
cnr_DATA.setModel(new DefaultTableModel(data,columns){
public Class getColumnClass(int col){
return String.class;
};
});
I am also updating the content of jtable dynamically from the database
DefaultTableModel model = (DefaultTableModel)cnr_DATA.getModel();
removeAllCurrentRows(model);
Vector<DocumentRow> data =
RecycleSQL.readRecycledDocuments();//this line returning vector of objects
for(DocumentRow object:data)
model.addRow(new string[]{object.getFilename(),
object.getTitle(),object.getLastTouched()
,object.getLastTouchedBy()});
model.setRowCount(data.size());
cnr_DATA.revalidate();
My problem is that mycellrenderer is not being called and is not wrapping the data. Could some one please advice me how to call it after updating the content of the JTable.
Update according to the suggestion of Madprogrammer and hovercraft
After modifying the code according to the suggestion. Now the cellrenderer is being called but it is resting the row height to default value. This is the logs from debug statement
[2013-08-02 01:20:53,335] [AWT-EventQueue-0] DEBUG MultiLineTableCellRenderer - setting row height 3 128
[2013-08-02 01:20:53,335] [AWT-EventQueue-0] DEBUG MultiLineTableCellRenderer - setting row height 3 16
which means, that after setting the height of the row correctly it is resting it back to the default value
This looks suspect to me:
cnr_DATA.setDefaultRenderer(String.class, r); // ?? String.class
Are you sure that the model holds String data, and that the column type returned by getColumnClass(...) returns String? Consider instead setting the cell renderer for the column that needs it.
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());
}
}
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);
}
});
}
}
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