Skip to main content

JXTreeTable with JCheckBox-Editor in JInternalFrames

5 replies [Last post]
peterpan123
Offline
Joined: 2010-01-28
Points: 0

I found a weird behavior with cellediting when using the JXTreeTable in a JInternalFrame.

I have a column where a checkbox should be displayed allowing the user to make it selected and unselected. When having my JXTreeTable inside a JInternalFrame with other components, the checkbox for cellediting doesn't change the state from selected to unselected and vice versa. Instead the focus is instantly being transfered back to the component that had the focus before (a textfield for example). When selecting a single cell in the JXTreeTable before clicking on the checkbox, the focus stays in the JXTreeTable and the checkbox state changes if i click it.

This problem only occurs when using a >>JInternalFrame<< that has additional Components like JTextFields beside the JXTreeTable.

The method getColumnClass(int col) in the TreeTableModel returns Boolean.class for this column. The method isCellEditable(Object node, int col) return true for this column. The method getValueAt(Object node, int col) returns the specified boolean value from my "userobject" for this column. The method setValueAt(Object value, Object Node, int col) sets the boolean value into my "userobject". However when facing the problem stated above, setValueAt is being called with the boolean-value my checkbox already has and not the new one.

I fixed this bug by overwriting the editCellAt(int row, int column, EventObject e) method from JXTreeTable and inserting the programcode that is being used in a JTable.

Let me know if you need some example code or point me to a bug report site for swinglabs.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
meb325
Offline
Joined: 2012-04-12
Points: 0

I am encountering the same issue. Would you mind posting the code for your fix?

kleopatra
Offline
Joined: 2003-06-11
Points: 0

hmm ... could be a similar issue as http://java.net/jira/browse/SWINGX-1489. If so, it's a core bug fixed in jdk7.

Cheers
Jeanette

meb325
Offline
Joined: 2012-04-12
Points: 0

Many thanks! I just tried jre 1.7.0_03-b05 and it works!

kleopatra
Offline
Joined: 2003-06-11
Points: 0

sounds like a bug ;-) Yeah, we need an small (!) runnable (!) standalone (!) example to that demonstrates the problem. Same as for all java-net projects, the swingx issue tracker is reachable from it's project home page, one item in the nav bar to the left

Thanks
Jeanette

peterpan123
Offline
Joined: 2010-01-28
Points: 0

quick example, using jdk6 and swingx1.6:

{noformat}
package somepackage;

import javax.swing.BoxLayout;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JTextField;
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.AbstractTreeTableModel;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;

public class Main {

private class CheckBoxTreeTableModel extends AbstractTreeTableModel {

public CheckBoxTreeTableModel(final DefaultMutableTreeTableNode root) {
super(root);
}

@Override
public Class<?> getColumnClass(final int col) {
if (col == 0) {
return String.class;
} else {
return Boolean.class;
}
}

@Override
public int getColumnCount() {
return 2;
}

@Override
public boolean isCellEditable(final Object node, final int col) {
return col == 1;
}

@Override
public Object getValueAt(final Object node, final int col) {
final DefaultMutableTreeTableNode castedNode =
(DefaultMutableTreeTableNode) node;
if (col == 0) {
return ((CheckBoxValueWrapper) castedNode.getUserObject()).
getDescription();
} else {
return ((CheckBoxValueWrapper) castedNode.getUserObject()).
getValue();
}
}

@Override
public void setValueAt(final Object value, final Object node,
final int col) {
if (col == 1) {
((CheckBoxValueWrapper) ((DefaultMutableTreeTableNode) node).
getUserObject()).setValue((Boolean) value);
}
}

@Override
public Object getChild(final Object parent, final int index) {
return ((DefaultMutableTreeTableNode) parent).getChildAt(index);
}

@Override
public int getChildCount(final Object parent) {
return ((DefaultMutableTreeTableNode) parent).getChildCount();
}

@Override
public int getIndexOfChild(final Object parent, final Object child) {
return 0;
}
}

private class CheckBoxValueWrapper {

private String description;
private boolean value;

public CheckBoxValueWrapper(final String description,
final boolean value) {
this.description = description;
this.value = value;
}

public String getDescription() {
return description;
}

public boolean getValue() {
return value;
}

public void setValue(final boolean value) {
this.value = value;
}
}

private CheckBoxTreeTableModel getTreeTableModel() {
final DefaultMutableTreeTableNode root =
new DefaultMutableTreeTableNode(null, true);
root.add(new DefaultMutableTreeTableNode(
new CheckBoxValueWrapper("first entry", true), false));
return new CheckBoxTreeTableModel(root);
}

public Main() {
final JFrame mainframe = new JFrame();
final JDesktopPane desktop = new JDesktopPane();
final JInternalFrame iFrame = new JInternalFrame();
final JTextField textfield = new JTextField();
final JXTreeTable treeTable = new JXTreeTable(getTreeTableModel());

iFrame.getContentPane().setLayout(
new BoxLayout(iFrame.getContentPane(), BoxLayout.X_AXIS));
iFrame.getContentPane().add(textfield);
iFrame.getContentPane().add(treeTable);
iFrame.setSize(200, 100);

mainframe.getContentPane().setLayout(
new BoxLayout(mainframe.getContentPane(), BoxLayout.X_AXIS));
mainframe.getContentPane().add(desktop);
mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainframe.setSize(320, 240);
desktop.add(iFrame);
iFrame.setVisible(true);
mainframe.setVisible(true);
}

public static void main(final String[] args) {
new Main();
}
}
{noformat}