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.
Related
I have a table model containing elements of type JCheckBox. I want the content of this table to be different according to the value of a JComboBox.
My problem is the following : if I toggle a few checkboxes and then change the value of my combo box, all the check boxes take the default value (this is what I want, because the boolean values are those of the selected item in the JCheckBox) except the last one I toggled before changing the value of the combo box.
And here is how I implemented this :
public class ValsSelectionTableModel extends MyAbstractTableModel {
private final JComboBox<Data> dataField;
private final Map<Data, JCheckBox[][]> modifiedVals = new HashMap<>();
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Data data = (Data) dataField.getSelectedItem();
if (!modifiedVals.containsKey(data))
modifiedVals.put(data,
buildCheckBoxesFrom(ClassWithStaticFields.defaultBoolArray));
return modifiedVals.get(data)[rowIndex][columnIndex];
}
private JCheckBox[][] buildCheckBoxesFrom(boolean[][] boolArray) {
JCheckBox[][] checkBoxArray =
new JCheckBox[boolArray.length][boolArray[0].length];
for (int i = 0 ; i < checkBoxArray.length ; i++)
for (int j = 0 ; j < checkBoxArray[i].length ; j++) {
checkBoxArray[i][j] = new JCheckBox();
checkBoxArray[i][j].setSelected(boolArray[i][j]);
checkBoxArray[i][j].setHorizontalAlignment(SwingConstants.CENTER);
}
return checkBoxArray;
}
}
Has anyone got an idea what's wrong with this ?
EDIT : I forgot something important (otherwise the JComboBox selection would not change the display) : I added this actionListener to my JComboBox :
public class MyListener implements ActionListener {
private final ValsSelectionTableModel tableModel;
public MyListener(ValsSelectionTableModel tableModel) {
this.tableModel = tableModel;
}
#Override
public void actionPerformed(ActionEvent e) {
tableModel.fireTableDataChanged();
}
}
Manage elements of type Boolean in your TableMode to get the default renderer and editor.
I already tried with Boolean, but the rendered checkboxes cannot be toggled.
Your implementation of TableMode appears to extend AbstractTableModel; ensure that the following things happen for the relevant column:
Return Boolean.class from getColumnClass().
Return true from isCellEditable().
Fire the appropriate TableModelEvent in setValueAt() when updating your internal Map<…>.
Complete examples using AbstractTableModel are seen here and here. An example of adding multiple components to a column is examined here.
I am using glazedlists for JComboBox in java to make a JComboBox searchable and sortable. But there is situation I can't get to solve it.
I have a JComboBox attached with glazedlists. glazedlists takes String array to fill this combobox and make it searchable like this
String[] Values = {"ABC", "DEF", "GHI", "JKL", "MNO"};
JComboBox cmb = new JComboBox();
AutoCompleteSupport.install(cmb , GlazedLists.eventListOf(Values));
This works good but the problem is that I want to add ID along with value coming from Database and for that I am implementing my own custom ListCellRenderer like this
class MyListRenderer extends JLabel implements ListCellRenderer
{
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Object[] itemData = (Object[])value;
setText((String)itemData[1]);
return this;
}
}
cmb.setRenderer(new MyListRenderer());
And to add value in JComboBox, I have to
while(rs.next()){
int id=rs.getInt("company_id");
String category=rs.getString("company_name");
Object[] itemData = new Object[] {id, category};
cmb.addItem(itemData);
}
Now how can I implement my JComboBox with glazedlists while setting my own custom renderer?
Didn't have any success with your way, but I found a solution in an earlier project. You can set the model of the JComboBox instead by doing something like this:
//load the list of objects to use
ContainerClass[] allOptions = ContainerClass.getAll();
//create an EventList with this list and set is as the combobox model
final EventList<ContainerClass> eventList = GlazedLists.eventList(Arrays.asList(allOptions));
comboBox.setModel(new DefaultComboBoxModel<ContainerClass>(allOptions));
//finally initialize the combobox by SwingUtilities if done on a non-UI thread
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AutoCompleteSupport<ContainerClass> install =
AutoCompleteSupport.install(comboBox, eventList);
install.setFilterMode(TextMatcherEditor.CONTAINS);
install.setHidesPopupOnFocusLost(true);
install.setSelectsTextOnFocusGain(false);
install.setCorrectsCase(false);
}
});
And with a ContainerClass like:
class ContainerClass{
int id;
String company;
//helper method to get all the objects needed
static ContainerClass[] getAll(){
ContainerClass test = new ContainerClass();
test.id = 2;
test.company = "abc";
return new ContainerClass[]{test,test,test};
}
#Override
//this String is what actually will be displayed in the combobox
public String toString(){return "(" + id + ") " + company;}
}
And I'm assuming that your JComboBox has the following type:
JComboBox<ContainerClass> comboBox;
(I had to obfuscate the names of all variables, so there might be errors in the code. Let me know and I will correct them)
So to recap. GlazedLists uses the model to get the names, which again asks the ContainerClass for it's toString() method which will return the name to display in the JComboBox.
As a note, when you call comboBox.getSelectedItem() it will return an object of type ContainerClass, or null if it isn't a valid selection.
UPDATE
If you want to be able to control the order as well as the name, you would need to implement your own model for the ComboBox. Found this that seems to explain it well:
class MyComboBoxModel extends AbstractListModel implements ComboBoxModel {
String[] ComputerComps = { "Monitor", "Key Board", "Mouse", "Joy Stick",
"Modem", "CD ROM", "RAM Chip", "Diskette" };
String selection = null;
public Object getElementAt(int index) {
return ComputerComps[index];
}
public int getSize() {
return ComputerComps.length;
}
public void setSelectedItem(Object anItem) {
selection = (String) anItem; // to select and register an
} // item from the pull-down list
// Methods implemented from the interface ComboBoxModel
public Object getSelectedItem() {
return selection; // to add the selection to the combo box
}
}
I ahve a JTable that is supposed to be 2 columns (String, JComboBox). When i initialize the table everything looks good. As soon as a I select a value in the table the JComboBox cell aquires the data type of the selected item.
I want to keep the JCOmboBox there and have it fire the events of data change and the Table ignore data changes in that column and keep the ComboBox populated.
My table has this as an override
#Override
public TableCellEditor getCellEditor(int row, int column) {
Object value = super.getValueAt(row, column);
if (value != null) {
if (value instanceof JComboBox) {
return new DefaultCellEditor((JComboBox) value);
}
return getDefaultEditor(value.getClass());
}
return super.getCellEditor(row, column);
}
Implementation
JComboBox uploadBox = new JComboBox();
uploadBox.addItem(MyPanel.UPLOAD_OPTIONS.PROMPT);
uploadBox.addItem(MyPanel.UPLOAD_OPTIONS.UPLOAD);
uploadBox.addItem(MyPanel.UPLOAD_OPTIONS.DONT_UPLOAD);
Object[][] tableData = new Object[][]{
{"Upload data on save", uploadBox}
};
table.setModel(
new DefaultTableModel(tableData, new String[]{"Description", "Options"}) {
Class[] types = new Class[]{String.class, JComboBox.class};
boolean[] canEdit = new boolean[]{false, true};
#Override
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit[columnIndex];
}
});
table.getColumnModel().getColumn(1).setCellRenderer(new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable jtable, Object o, boolean bln, boolean bln1, int i, int i1) {
return (Component)o;
}
});
answer is quite simple don't put JComboBox to the XxxTableModel or to set getColumClass for JComboBox.class, this is wrong (sure is possible but with bunch of side effects), XxxTableModel (is designated for) can hold directly only standard Java data types (String, Date, Icon/ImageIcon, Integer, Double etc... )
XxxTableModel should be store (if you don't want to parsing between Java data types) the same data type like as is stored in DefaultComboBoxModel (noting clear what constans are MyPanel.XXX), e.g in XxxTableModel is stored String value when DefaultComboBoxModel has the same data types, similair logics for Date, Icon/ImageIcon, Integer or Double
for more info to read Oracle tutorial How to use Tables - Using a Combo Box as an Editor
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.
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.