Unable to lose jComboBox in a jTable focus - java

I have a jTable that has a jComboBox column. However I had an issue where I couldn't get the jComboBox to show unless you first click on it. Other people have had the same problem, it seems.
So I then learned I needed to make a CellRenderer besides the CellEditor. And so I did...
public class MyCellRenderer extends JComboBox<CustomItem> implements TableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
if(isSelected){
setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
} else{
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setSelectedItem(value);
return this;
}
}
By the way, I am also using a ComboBoxRenderer because I need it to display text while containing an item.
public class MyComboBoxRenderer extends BasicComboBoxRenderer{
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus){
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if(value != null){
CustomItem customItem = (CustomItem) value;
setText(customItem.getText());
}
if(index == -1){
CustomItem customItem = (CustomItem) value;
setText("" + customItem.getText());
}
return this;
}
}
And now it works! It does show the jComboBox in my jTable by default BUT now each jComboBox on each row has permanent focus! And only the first one I click on actually displays the menu. The rest are 'selected' but they do not respond.
Edit: Here is how I create the table.
private void initializeTable(){
JTable jTable1 = new javax.swing.JTable();
DefaultTableModel dtm = new DefaultTableModel();
dtm.addColumn("one");
dtm.addColumn("two");
dtm.addColumn("three");
jTable1.setModel(dtm);
JComboBox<CustomItem> items = new JComboBox<>();
items.setRenderer(new MyComboBoxRenderer());
items.add(new CustomItem(1, "soup", false);
items.add(new CustomItem(33, "sauce", false);
items.setSelectedIndex(0);
jTable1.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(items));
jTable1.getColumnModel().getColumn(2).setCellRenderer(new MyCellRenderer());
}

Related

JTable cells getting overlapped

I have implemented a JTree and populated some data. The table contains three columns and based on some values on a specific cell it should have either labels or combo boxes. All the values in the 3rd column are editable. I too have a JTree from which a node is selected and based on it the table values change accordingly. The issue exists when I edit a cell in the table and move to another node in the tree (which populates a new set of data in the table), the previously edited cell values exist in the table on top of the new cell values. Below is how I implemented TableCellRenderer and TableCellEditor. I might have used some concepts wrong since I am a beginner for swing. Please help me figure out what I have done incorrectly.
public void populateTableData(List<Field> list,JTree jTree){
fieldList = null;
tcBuilderTree = jTree;
fieldList = list;
md=new PropertiesTableModel(fieldList);
getPropertieseTable().setModel(md);
final TableCellRenderer cellRenderer = new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable arg0,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int col) {
if(value instanceof List<?>) {
List<Value> valueList=(ArrayList)value;
return createComboBox(valueList);
}
else{
JLabel lbl=new JLabel();
lbl.setText((String)value);
return lbl;
}
}
};
propertiesTable.setDefaultRenderer(Object.class, cellRenderer);
final TableCellEditor cellEditor = new TableCellEditor() {
private DefaultCellEditor textEditor;
private DefaultCellEditor currentEditor;
#Override
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean isSelected,
int row,
int column) {
textEditor = new DefaultCellEditor(new JTextField());
PropertiesTableModel model = (PropertiesTableModel) table.getModel();
List<Value> values = model.getPossibleValues(row, column);
if (values != null) {
List<Value> valueList=(ArrayList)value;
currentEditor = new DefaultCellEditor(createComboBox(valueList));
} else {
currentEditor = textEditor;
}
return currentEditor.getTableCellEditorComponent(table, value,
isSelected, row, column);
}
#Override
public Object getCellEditorValue() {
return currentEditor.getCellEditorValue();
}
#Override
public boolean isCellEditable(EventObject anEvent) {
JTable tbl = (JTable) anEvent.getSource();
int row, col;
if (anEvent instanceof MouseEvent) {
MouseEvent evt = (MouseEvent) anEvent;
row = tbl.rowAtPoint(evt.getPoint());
col = tbl.columnAtPoint(evt.getPoint());
} else {
row = tbl.getSelectedRow();
col = tbl.getSelectedColumn();
}
if(col<2){
return false;
}
else
{
return true;
}
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
#Override
public boolean stopCellEditing() {
Object obj = currentEditor.getCellEditorValue();
fieldList.get(propertiesTable.getEditingRow())
.setDefaultValue(obj);
return currentEditor.stopCellEditing();
}
#Override
public void cancelCellEditing() {
currentEditor.cancelCellEditing();
}
#Override
public void addCellEditorListener(CellEditorListener l) {
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
}
};
propertiesTable.setDefaultEditor(Object.class,cellEditor);
}
The issue exists when I edit a cell in the table and move to another node in the tree (which populates a new set of data in the table), the previously edited cell values exist in the table on top of the new cell values.
I would guess you are not stopping editing of the table cell before you reload the table with new data.
You probably should add the following to your code when you create the JTable:
JTable table = new JTable(...);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
See Table Stop Editing for more information.
The table contains three columns and based on some values on a specific cell it should have either labels or combo boxes
You may not need to create custom editors. Just have the table choose the appropriate default editor based on the cell being edited. You can do this by overriding the getCellEditor(...) method of the JTable. Check out: How to add unique JComboBoxes to a column in a JTable (Java) for an example of this approach.

Color Cell based on value

im using JXTable and trying to color the row based on value, BUT the show empty(but the render is running because it show the syso in console)
public class MyCellRenderer extends JLabel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) {
SimpleTableModel mymodel = (SimpleTableModel) jxtableListar.getModel();
ModelProtocolo actualModel= (ModelProtocolo ) mymodel.getProtocolo(rowIndex) ;
if(actualModel.getValue() > 0) {
System.out.println("Yep the Render is working");
}
return this;
}
}
jxtableListar.setDefaultRenderer(Object.class, new MyCellRenderer ());
i did not found any usefull "tutorial" how to use the JXTable renderer, since they talk about something about Hightlight, but all the tutorials are "out of information" to learn
is there any good way/tutorial to color a JXTable row base on a value of the cell?
Your renderer is returning a JLabel (itself) that hasn't had anything set on it. Instead, extend DefaultTableCellRenderer:
public class MyCellRenderer extends DefaultTableCellRenderer {
#override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) {
SimpleTableModel mymodel = (SimpleTableModel) jxtableListar.getModel();
ModelProtocolo actualModel= (ModelProtocolo ) mymodel.getProtocolo(rowIndex) ;
JLabel label = (JLabel) super.getTableCellRendererComponent(/* pass in all params */);
label.setText(/*whatever the text should be*/);
label.setBackground(/*whatever the color should be*/);
return label;
}
}

TableModel Change the value of a jcheckbox cell after a second click in other checkbox

I have a table with a checkbox column, I am able to show the table like i want and I make editable just the column where the checkbox is placed. The problem is when I select the checkbox the render paint in the right way the checkbox but the value in the tablemodel isn't changed, this value just change until i give click in another checkbox, always the last checkbox that I choose doesn't reflects his value in the TableModel. The classes that I am using are:
Checkcell
class CheckCell extends DefaultCellEditor implements TableCellRenderer{
private JComponent component = new JCheckBox();
private boolean value = false;
public CheckCell() {
super(new JCheckBox());
}
#Override
public Object getCellEditorValue() {
return ((JCheckBox)component).isSelected();
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
( (JCheckBox) component).setBackground( new Color(200,200,0) );
boolean b = ((Boolean) value).booleanValue();
( (JCheckBox) component).setSelected( b );
( (JCheckBox) component).setHorizontalAlignment(SwingConstants.CENTER);
return ( (JCheckBox) component);
}
#Override
public boolean stopCellEditing() {
value = ((Boolean)getCellEditorValue()).booleanValue() ;
((JCheckBox)component).setSelected( value );
return super.stopCellEditing();
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null)
return null;
return ( (JCheckBox) component );
}
}
CheckRender
class CheckRender extends JCheckBox implements TableCellRenderer {
private JComponent component = new JCheckBox();
public CheckRender() {
setOpaque(true);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
((JCheckBox) component).setBackground( new Color(0,200,0));
boolean b = ((Boolean) value).booleanValue();
((JCheckBox) component).setSelected(b);
((JCheckBox) component).setHorizontalAlignment(SwingConstants.CENTER);
return ((JCheckBox) component);
}
}
My Model
class DynaTableModel extends DefaultTableModel {
public DynaTableModel() {
super();
}
public DynaTableModel(final DynaTableBean dynaBean) {
super(dynaBean.getContent(), dynaBean.getHeaders());
}
#Override
public boolean isCellEditable(int row, int col) {
if (col == 0)
{
return true;
} else {
return false;
}
}
#Override
public void setValueAt(Object value, int row, int column) {
super.setValueAt(value, row, column);
}
Could you help me with this? what is missing me to change the value in the jtable when this change in the checkbox.
I am new in java and I think that there are something that is missing me.
Thanks in advanced.
Being a little more explicity, when I ticked the checkbox and I tried to recover the value from the TableModel the value is wrong by example if I ticked the first checkbox and I tried to recover the value using:
valor = (Boolean) tablemodel.getValueAt(i, 0);
I am getting false when this should be true, but if I check the first checkbox and later the second one the value of the first checkbox now is fine(true) but the second is still false is a kind of bug but I don't find the way to avoid this.
Someone knows how to avoid this.
I have a table with a checkbox column, I am able to show the table
like i want and I make editable just the column where the checkbox is
placed. The problem is when I select the checkbox the render paint in
the right way the checkbox but the value in the tablemodel isn't
changed, this value just change until i give click in another
checkbox, always the last checkbox that I choose doesn't reflects his
value in the TableModel
JTable has built in support for JCheckBox as TableCellRenderer and Editor
Boolean value represens JCheckBox in XxxTableModel, you would need to put there true or false (1st column)
override public Class getColumnClass(int c) {,

Java: JComboBox inside JTable - setSelectedIndex has no effect on GUI

I am having a JTable with two columns. In the second column there are different editors (JTextField, JComboBox and CheckComboBox), in each row one. This works fine so far however I have implemented a reset option which changes the whole JTable back to the original state (resets all changes).
The problem I am facing now is that when I programmatical change the index of a ComboBox with setSelectedIndex I see no result in the GUI although the model fires its change with fireTableDataChanged and is also receivied by an TableModelListener of the Table. When I lookup the changed ComboBox I also get the correct index however it is not shown in the GUI. I also tried the methods revalidate, updateUI and repaint wihtout any change.
The problem might lay in the architecture of it (maybe the Renderer?). Here is my Editor/Renderer class.
class VEachRowEditor implements TableCellEditor, TableCellRenderer {
protected Hashtable<Integer, TableCellEditor> editors;
protected TableCellEditor editor, defaultEditor, renderer;
JTable table;
VEachRowEditorManager rowmanager;
public VEachRowEditor(JTable table, VEachRowEditorManager rowmanager) {
this.table = table;
editors = new Hashtable<Integer, TableCellEditor>();
defaultEditor = new DefaultCellEditor(new JTextField());
this.rowmanager = rowmanager;
}
public void setEditorAt(int row, TableCellEditor editor) {
if (editor instanceof DefaultCellEditor)
((DefaultCellEditor) editor).setClickCountToStart(1);
editors.put(new Integer(row), editor);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
editor = (TableCellEditor) editors.get(new Integer(row));
if (editor == null) {
editor = defaultEditor;
}
return editor.getTableCellEditorComponent(table, value, isSelected,
row, column);
}
public Object getCellEditorValue() {
return editor.getCellEditorValue();
}
public final boolean stopCellEditing() {
return editor.stopCellEditing();
}
public void cancelCellEditing() {
editor.cancelCellEditing();
}
public boolean isCellEditable(EventObject anEvent) {
selectEditor((MouseEvent) anEvent);
return editor.isCellEditable(anEvent);
}
public void addCellEditorListener(CellEditorListener l) {
editor.addCellEditorListener(l);
}
public void removeCellEditorListener(CellEditorListener l) {
editor.removeCellEditorListener(l);
}
public boolean shouldSelectCell(EventObject anEvent) {
selectEditor((MouseEvent) anEvent);
return editor.shouldSelectCell(anEvent);
}
protected void selectEditor(MouseEvent e) {
int row;
if (e == null) {
row = table.getSelectionModel().getAnchorSelectionIndex();
} else {
row = table.rowAtPoint(e.getPoint());
}
editor = (TableCellEditor) editors.get(new Integer(row));
if (editor == null) {
System.out.println(editor);
editor = defaultEditor;
}
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
renderer = (TableCellEditor) editors.get(new Integer(row));
if (renderer == null) {
renderer = defaultEditor;
}
return renderer.getTableCellEditorComponent(table, value, isSelected,
row, column);
}
}
Is the getTableCellEditorComponent wrong?
The rowmanager holds all the JComboBoxes and CheckComboBoxes with all the models.
when I programmatical change the index of a ComboBox with setSelectedIndex I see no result in the GUI
Renderer and editers just display the data in the model. Don't reset the editor component.
Reset the data in the model. ie>
table.setValueAt(...); // or
table.getModel().setValueAt(...);

Issues with add JButton in the table

I am adding Jbutton to a table by extendibg AbstractCellEditor class. But on click of button the text doesnt change from "Start" to "Stop" .here is the class i implemented
public class ButtonEditor1 extends AbstractCellEditor implements
TableCellEditor,ActionListener,TableCellRenderer{
JButton btnSTART = new JButton("START");
private JTable table ;
public ButtonEditor1(JTable table){
this.table = table;
btnSTART.addActionListener(this);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
return btnSTART;
}
public Object getCellEditorValue() {
// TODO Auto-generated method stub
return btnSTART;
}
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
if(btnSTART.getText().equals("START")){
if(row != -1){
btnSTART.setText("STOP");
}
}else if(btnSTART.getText().equals("STOP")){
if(row != -1){
btnSTART.setText("START");
}
}
fireEditingStopped();
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
return btnSTART;
}
}
what i am doing wrong .. I have a Model class which takes the column as JButton and have overriden the method setValueAt and getValueAt.
A JTable uses renderers to display data. Once you click on the cell using the button as an editor, the button editor is invoked for a split second, then the cell is placed back in rendering mode. So if you want to change the text you change the value in the model.

Categories

Resources