Skip to main content

Does JXTreeTable support editing nodes via table?

13 replies [Last post]
pitoniak
Offline
Joined: 2008-09-09
Points: 0

I have spent days searching for the answer to this problem. here is my code. i want the checkboxes in the JXTYreeTable's table to update the value, but for the life of me cannot figure out what to do. andy help would eb so greatly appreciated :)

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Date;

import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.AbstractMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;

public class JXTreeTableJPanel extends JPanel implements ActionListener, JXTreeTableJPanelConstants{
private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(JXTreeTableJPanel.class);
private JXTTreeTableNode rootJXTTreeTableNode = null;
private DemoTreeTableModel demoTreeTableModel = null;
private JXTreeTable jXTreeTable = null;

public JXTreeTableJPanel(){
GridBagConstraints gridBagConstraints = null;
rootJXTTreeTableNode = new JXTTreeTableNode("root", true);
demoTreeTableModel = new DemoTreeTableModel(rootJXTTreeTableNode);
jXTreeTable = new JXTreeTable(demoTreeTableModel);
jXTreeTable.setRootVisible(true);

jXTreeTable.addMouseListener(new JXTreeTablePopupMenuListener(this));
jXTreeTable.setDefaultEditor(Boolean.class, new DefaultCellEditor(new JCheckBox()));

this.setLayout(new GridBagLayout());

JScrollPane jXTreeTableJTableJscrollPane = new JScrollPane(jXTreeTable);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 1;
gridBagConstraints.gridheight = 1;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.anchor = GridBagConstraints.WEST;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(0,0,0,10);//int top, int left, int bottom, int right
gridBagConstraints.ipadx = 0;
gridBagConstraints.ipady = 0;
this.add(jXTreeTableJTableJscrollPane, gridBagConstraints);
}

public JXTTreeTableNode addTreeNode(JXTTreeTableNode parent, String name, boolean enabled){
JXTTreeTableNode jXTTreeTableNode = null;

parent = parent==null ? rootJXTTreeTableNode : parent;
jXTTreeTableNode = new JXTTreeTableNode(name, enabled);
demoTreeTableModel.insertNodeInto(jXTTreeTableNode, parent, parent.getChildCount());

return jXTTreeTableNode;
}

public void expandRoot(){
jXTreeTable.expandPath(new TreePath(rootJXTTreeTableNode));
}

private static class DemoTreeTableModel extends DefaultTreeTableModel {
public DemoTreeTableModel(JXTTreeTableNode jXTTreeTableNode) {
super(jXTTreeTableNode);
}

/**
* {@inheritDoc}
*/
@Override
public Object getValueAt(Object node, int column) {
JXTTreeTableNode jXTreeTableNode = (JXTTreeTableNode) node;

Object o = jXTreeTableNode.getUserObject();

switch (column) {
case 0:
return o.toString();
case 1:
return o.hashCode();
case 2:
return o.hashCode() % 2 == 0;
case 3:
return new Date(o.hashCode());
case 4:
return jXTreeTableNode.isEnabled();
}
return super.getValueAt(node, column);
}

/**
* Tells if a column can be edited.
*/
public boolean isCellEditable(Object node, int column) {
return true;
}

/**
* {@inheritDoc}
*/
@Override
public Class<?> getColumnClass(int column) {
switch (column) {
case 0:
return String.class;
case 1:
return Integer.class;
case 2:
return Boolean.class;
case 3:
return Date.class;
case 4:
return Boolean.class;
default:
return Object.class;
}
}

/**
* {@inheritDoc}
*/
@Override
public int getColumnCount() {
return 5;
}

/**
* {@inheritDoc}
*/
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "String";
case 1:
return "Hash Code";
case 2:
return "Divisible By 2";
case 3:
return "Hash Code As Date";
case 4:
return "Enabled";
default:
return "Column " + (column + 1);
}
}
}

private static class JXTTreeTableNode extends AbstractMutableTreeTableNode {
private boolean enabled = false;

public JXTTreeTableNode(String name, boolean enabled){
super(name);
this.enabled = enabled;
}

public boolean isEnabled() {
return enabled;
}

public int getColumnCount() {
// TODO Auto-generated method stub
return 0;
}

public Object getValueAt(int arg0) {
// TODO Auto-generated method stub
return null;
}
}

/*mousePressed() occurs when the user presses the mouse button.
mouseReleased() occurs when the user releases the mouse button.
mouseClicked() occurs when the user presses and releases the mouse button. A user
normally clicks the mouse button when selecting or double clicking an icon.
(A double click is two mouse clicks in succession.) A mouse action will not result in a
click if the user moves the mouse before releasing the button.
Since a mouse click is the combination of pressing and releasing the mouse button, before
the event is dispatched to the mouseClicked() method, the mousePressed() and mouseReleased()
methods will both be called.
mouseEntered() occurs when the mouse leaves its current component and enters the component
you are listening to.
mouseExited() occurs when the mouse leaves the component you are listening to. This event
occurs the instant the mouse pointer no longer resides over the component.
mouseDragged() occurs when the user presses the mouse button and moves the mouse before
releasing the button. Releasing the mouse button after a mouseDragged() will not result
in a mouseClicked().
mouseMoved() occurs when the mouse moves within the component without being dragged.*/
private class JXTreeTablePopupMenuListener extends MouseAdapter {
ActionListener actionListener = null;

public JXTreeTablePopupMenuListener(ActionListener actionListener){
this.actionListener = actionListener;
}

//Invoked when the mouse cursor has been moved onto a component
//but no buttons have been pushed.
public void mouseMoved(MouseEvent e){

}

//On some platforms, mouseReleased sets PopupTrigger.
public void mouseReleased(MouseEvent e){
if(e.isMetaDown()){
int row = jXTreeTable.rowAtPoint(new Point(e.getX(), e.getY()));
if(row != -1){
jXTreeTable.setRowSelectionInterval(row, row);
}
}
checkPopup(e);
}

//And on other platforms, mousePressed sets PopupTrigger.
public void mousePressed(MouseEvent e){
checkPopup(e);
}

/*The exact gesture that should bring up a popup menu varies by look
and feel. In Microsoft Windows, the user by convention brings up a
popup menu by releasing the right mouse button while the cursor is
over a component that is popup-enabled. In the Java look and feel,
the customary trigger is either pressing the right mouse button
(for a popup that goes away when the button is released) or clicking
it (for a popup that stays up). In a future release, a new mechanism
for automatically triggering popup menus in the appropriate way for
the look and feel might be added.*/
private void checkPopup(MouseEvent e){
JPopupMenu jTreePopupMenu = null;
JMenuItem menuItem = null;

//e.isPopupTrigger() Returns whether or not this mouse
//event is the popup menu trigger event for the platform.
if (e.isPopupTrigger()){
jTreePopupMenu = new JPopupMenu();

menuItem = new JMenuItem(ADD_TREENODE);
menuItem.addActionListener(actionListener);
jTreePopupMenu.add(menuItem);

TreePath treePath = jXTreeTable.getTreeSelectionModel().getSelectionPath();
JXTTreeTableNode treeNode =(JXTTreeTableNode)treePath.getLastPathComponent();
if(!treeNode.equals(rootJXTTreeTableNode)){
menuItem = new JMenuItem(DELETE_TREENODE);
menuItem.addActionListener(actionListener);
jTreePopupMenu.add(menuItem);
}
jTreePopupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
}

public void actionPerformed(ActionEvent actionEvent) {
try{
TreePath treePath = jXTreeTable.getTreeSelectionModel().getSelectionPath();
JXTTreeTableNode treeNode =(JXTTreeTableNode)treePath.getLastPathComponent();
if (actionEvent.getActionCommand().equals(ADD_TREENODE)){
addTreeNode(treeNode, "poopppp", false);
jXTreeTable.expandPath(treePath);
}else if (actionEvent.getActionCommand().equals(DELETE_TREENODE)){
demoTreeTableModel.removeNodeFromParent(treeNode);
}
}catch(Exception e){
logger.error(e, e);
}
}

public static void main(String[] args) {
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setSize(600, 400);
JXTreeTableJPanel jXTreeTableJPanel = new JXTreeTableJPanel();
jXTreeTableJPanel.addTreeNode(null, "name", true);
frame.setContentPane(jXTreeTableJPanel);
frame.setVisible(true);
jXTreeTableJPanel.expandRoot();
}
});
}catch(Exception e){
e.printStackTrace();
}
}

}

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
rturnbull
Offline
Joined: 2005-08-27
Points: 0

Thanks.
That clears it up for me.

rturnbull
Offline
Joined: 2005-08-27
Points: 0

> Second, your demo does not compile because
> JXTreeTableJPanelConstants is missing. It also
> sounds like it's similar in function to
> SwingConstants. Please review Effective Java to
> discover why that's a bad idea.

As I don't have the book, could you possibly take the time to
elaborate on this.
I searched for sample chapters but couldn't find anything specific.

Thanks

pitoniak
Offline
Joined: 2008-09-09
Points: 0

Hi,

I think what Karl was telling me was, that placing constants in an interface, and then having your class implement that interface is considered bad form. the appropriate approach is to place them in a class, and then have my code reference them as ClassName.CONST. The good news is i learned what i was doing was wrong, the bad news is that Eclipse does not easily refactor this case, and my code is full of this usage pattern. slow cleanup on my end.

regards,

mike

kschaefe
Offline
Joined: 2006-06-08
Points: 0

Mike's got it. It is considered bad form to create an interface for the purpose of containing and dissemintaing constants. An interface should define a type. What does (o instanceof SwingConstants) do for you? It's not a type and you wouldn't ever use it as a type. An interface should define at least one method to be a type. CheckStyle and PMD have checks for this case to avoid the anti-pattern.

Karl

pitoniak
Offline
Joined: 2008-09-09
Points: 0

here is an even closer pass at the problem.
now treenodes are editable, but they get clipped if the new node name is longer than the original. am i doing something wrong?

thx,

mike

[code]

import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Date;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.TableColumn;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate.ColumnHighlightPredicate;
import org.jdesktop.swingx.treetable.AbstractMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;

public class JXTreeTableJPanel extends JPanel implements ActionListener, TableModelListener, TreeSelectionListener{
private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(JXTreeTableJPanel.class);
private JXTTreeTableNode rootJXTTreeTableNode = null;
private MyTreeTableModel demoTreeTableModel = null;
private JXTreeTable jXTreeTable = null;

public JXTreeTableJPanel(){
GridBagConstraints gridBagConstraints = null;
rootJXTTreeTableNode = new JXTTreeTableNode("root", "test", true, 1);
demoTreeTableModel = new MyTreeTableModel(rootJXTTreeTableNode);
jXTreeTable = new JXTreeTable(demoTreeTableModel);
jXTreeTable.setRootVisible(true);
jXTreeTable.getTableHeader().setReorderingAllowed(false);
TableColumn column = jXTreeTable.getColumn("Count");
JComboBox combo = new JComboBox();
combo.addItem(1);
combo.addItem(2);
column.setCellEditor(new DefaultCellEditor(combo));

//TODO broke??
jXTreeTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

TableColumn t_constraintColumn = jXTreeTable.getColumnModel().getColumn(5);

jXTreeTable.addHighlighter(new AlignmentHighlighter(AlignmentHighlighter.CENTER,
new ColumnHighlightPredicate(5)));

jXTreeTable.addMouseListener(new JXTreeTablePopupMenuListener(this));

jXTreeTable.getModel().addTableModelListener(this);
jXTreeTable.addTreeSelectionListener(this);

//jXTreeTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

//entry

//Setup Highlighters...
Highlighter myHighlighter = new ColorHighlighter(
HighlightPredicate.ROLLOVER_ROW, Color.lightGray, Color.red);
jXTreeTable.addHighlighter(myHighlighter);

this.setLayout(new GridBagLayout());

JScrollPane jXTreeTableJTableJscrollPane = new JScrollPane(jXTreeTable);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 1;
gridBagConstraints.gridheight = 1;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.anchor = GridBagConstraints.WEST;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(0,0,0,0);//int top, int left, int bottom, int right
gridBagConstraints.ipadx = 0;
gridBagConstraints.ipady = 0;
this.add(jXTreeTableJTableJscrollPane, gridBagConstraints);
}

public JXTTreeTableNode addTreeNode(JXTTreeTableNode parent, String name, boolean enabled){
JXTTreeTableNode jXTTreeTableNode = null;

parent = parent==null ? rootJXTTreeTableNode : parent;
jXTTreeTableNode = new JXTTreeTableNode(name, name, enabled, 2);
demoTreeTableModel.insertNodeInto(jXTTreeTableNode, parent, parent.getChildCount());

return jXTTreeTableNode;
}

public void expandRoot(){
jXTreeTable.expandPath(new TreePath(rootJXTTreeTableNode));
}

public void tableChanged(TableModelEvent tableModelEvent) {
System.out.println("model change");
//((JXTreeTable)tableModelEvent.getSource()).updateUI();
}

public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
TreePath treePath = treeSelectionEvent.getPath();
if(treePath != null){
JXTTreeTableNode jXTTreeTableNode = (JXTTreeTableNode)treePath.getLastPathComponent();
System.out.println("TreeSelectionEvent: "+ jXTTreeTableNode.getName());
}
}

public void actionPerformed(ActionEvent actionEvent) {
try{
TreePath treePath = jXTreeTable.getTreeSelectionModel().getSelectionPath();
JXTTreeTableNode treeNode =(JXTTreeTableNode)treePath.getLastPathComponent();
if (actionEvent.getActionCommand().equals(MyConstants.ADD_TREENODE)){
String nodeName = JOptionPane.showInputDialog(this, "Node Name");
addTreeNode(treeNode, nodeName, false);
jXTreeTable.expandPath(treePath);
}else if (actionEvent.getActionCommand().equals(MyConstants.DELETE_TREENODE)){
demoTreeTableModel.removeNodeFromParent(treeNode);
}
}catch(Exception e){
logger.error(e, e);
}
}

private static class JXTTreeTableNode extends AbstractMutableTreeTableNode {
private String name = null;
private String column1 = null;
private boolean enabled = false;
private boolean divisible = false;
private int count = 0;

public JXTTreeTableNode(String name, String column1, boolean enabled, int count){
super(name);
this.name = name;
this.column1 = column1;
this.enabled = enabled;
this.count = count;
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled){
this.enabled = enabled;
}

public int getColumnCount() {
// TODO Auto-generated method stub
return 0;
}

public Object getValueAt(int arg0) {
// TODO Auto-generated method stub
return null;
}

public boolean isDivisible() {
return divisible;
}

public void setDivisible(boolean divisible) {
this.divisible = divisible;
}

public String getColumn1() {
return column1;
}

public void setColumn1(String column1) {
this.column1 = column1;
}

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String toString(){
return name;
}
}

private static class MyTreeTableModel extends DefaultTreeTableModel {

public MyTreeTableModel(JXTTreeTableNode jXTTreeTableNode) {
super(jXTTreeTableNode);
}

/**
* {@inheritDoc}
*/
@Override
public Object getValueAt(Object node, int column) {
JXTTreeTableNode jXTreeTableNode = (JXTTreeTableNode) node;

Object o = jXTreeTableNode.getUserObject();

switch (column) {
case 0:
return jXTreeTableNode.getName();
case 1:
return jXTreeTableNode.getColumn1();
case 2:
return jXTreeTableNode.isDivisible();
case 3:
return new Date(o.hashCode());
case 4:
return jXTreeTableNode.isEnabled();
case 5:
return jXTreeTableNode.getCount();
}
return super.getValueAt(node, column);
}

/*
*
* First, please wrap code in [code]..[/code] tags.
Second, your demo does not compile because JXTreeTableJPanelConstants is missing. It also sounds like it's similar in function to SwingConstants. Please review Effective Java to discover why that's a bad idea.
Third, the edits fail to save because you are not saving them. Your model should implement setValueAt. Since you're using (extending) the default model, the place that you need to add the setValueAt is in the node.
Fourth, I consider it bad practice to extend DefaultTreeTableModel, it was not designed for extension.

Karl

*/

public void setValueAt(Object value, Object node, int column) {
super.setValueAt(value,node,column);

JXTTreeTableNode jXTreeTableNode = (JXTTreeTableNode) node;
Object o = jXTreeTableNode.getUserObject();

switch (column) {
case 0:
jXTreeTableNode.setName((String)value);
break;

case 1:
jXTreeTableNode.setColumn1((String)value);
break;

case 2:
jXTreeTableNode.setDivisible((Boolean)value);
break;
case 4:
jXTreeTableNode.setEnabled((Boolean)value);
break;
case 5:
jXTreeTableNode.setCount((Integer)value);
break;

//other cases
default:

}
}

/**
* Tells if a column can be edited.
*/
public boolean isCellEditable(Object node, int column) {
switch (column) {
case 0:
return true;
case 3:
return false;
default:
return true;
}
}

/**
* {@inheritDoc}
*/
@Override
public Class getColumnClass(int column) {
switch (column) {
case 0:
return String.class;
case 1:
return String.class;
case 2:
return Boolean.class;
case 3:
return Date.class;
case 4:
return Boolean.class;
case 5:
return Integer.class;
default:
return Object.class;
}
}

/**
* {@inheritDoc}
*/
@Override
public int getColumnCount() {
return 6;
}

/**
* {@inheritDoc}
*/
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "TableName";
case 1:
return "Column1 Title";
case 2:
return "Column2 Title";
case 3:
return "Column3 Title";
case 4:
return "Enabled";
case 5:
return "Count";

default:
return "Column " + (column + 1);
}
}
}

/*mousePressed() occurs when the user presses the mouse button.
mouseReleased() occurs when the user releases the mouse button.
mouseClicked() occurs when the user presses and releases the mouse button. A user
normally clicks the mouse button when selecting or double clicking an icon.
(A double click is two mouse clicks in succession.) A mouse action will not result in a
click if the user moves the mouse before releasing the button.
Since a mouse click is the combination of pressing and releasing the mouse button, before
the event is dispatched to the mouseClicked() method, the mousePressed() and mouseReleased()
methods will both be called.
mouseEntered() occurs when the mouse leaves its current component and enters the component
you are listening to.
mouseExited() occurs when the mouse leaves the component you are listening to. This event
occurs the instant the mouse pointer no longer resides over the component.
mouseDragged() occurs when the user presses the mouse button and moves the mouse before
releasing the button. Releasing the mouse button after a mouseDragged() will not result
in a mouseClicked().
mouseMoved() occurs when the mouse moves within the component without being dragged.*/
private class JXTreeTablePopupMenuListener extends MouseAdapter {
ActionListener actionListener = null;

public JXTreeTablePopupMenuListener(ActionListener actionListener){
this.actionListener = actionListener;
}

//Invoked when the mouse cursor has been moved onto a component
//but no buttons have been pushed.
public void mouseMoved(MouseEvent e){

}

//On some platforms, mouseReleased sets PopupTrigger.
public void mouseReleased(MouseEvent e){
if(e.isMetaDown()){
int row = jXTreeTable.rowAtPoint(new Point(e.getX(), e.getY()));
if(row != -1){
jXTreeTable.setRowSelectionInterval(row, row);
}
}
checkPopup(e);
}

//And on other platforms, mousePressed sets PopupTrigger.
public void mousePressed(MouseEvent e){
checkPopup(e);
}

/*The exact gesture that should bring up a popup menu varies by look
and feel. In Microsoft Windows, the user by convention brings up a
popup menu by releasing the right mouse button while the cursor is
over a component that is popup-enabled. In the Java look and feel,
the customary trigger is either pressing the right mouse button
(for a popup that goes away when the button is released) or clicking
it (for a popup that stays up). In a future release, a new mechanism
for automatically triggering popup menus in the appropriate way for
the look and feel might be added.*/
private void checkPopup(MouseEvent e){
JPopupMenu jTreePopupMenu = null;
JMenuItem menuItem = null;

//e.isPopupTrigger() Returns whether or not this mouse
//event is the popup menu trigger event for the platform.
if (e.isPopupTrigger()){
jTreePopupMenu = new JPopupMenu();

menuItem = new JMenuItem(MyConstants.ADD_TREENODE);
menuItem.addActionListener(actionListener);
jTreePopupMenu.add(menuItem);

TreePath treePath = jXTreeTable.getTreeSelectionModel().getSelectionPath();
JXTTreeTableNode treeNode =(JXTTreeTableNode)treePath.getLastPathComponent();
if(!treeNode.equals(rootJXTTreeTableNode)){
menuItem = new JMenuItem(MyConstants.DELETE_TREENODE);
menuItem.addActionListener(actionListener);
jTreePopupMenu.add(menuItem);
}
jTreePopupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
}

/**
*
* @author Martin Miller
*/
private class AlignmentHighlighter extends AbstractHighlighter implements SwingConstants {
public int alignment;

public AlignmentHighlighter(int alignment) {
this(alignment, null);
}

public AlignmentHighlighter(int alignment, HighlightPredicate predicate) {
super(predicate);
this.alignment = alignment;
}

protected Component doHighlight(Component renderer, ComponentAdapter adapter) {
applyAlignment(renderer, adapter);
return renderer;
}

protected void applyAlignment(Component renderer, ComponentAdapter adapter) {
((JLabel)renderer).setHorizontalAlignment(alignment);
}
}

private class MyConstants{
public static final String ADD_TREENODE = "Add";
public static final String DELETE_TREENODE = "Delete";
}

public static void main(String[] args) {
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setSize(600, 400);
JXTreeTableJPanel jXTreeTableJPanel = new JXTreeTableJPanel();
jXTreeTableJPanel.addTreeNode(null, "name", true);
frame.setContentPane(jXTreeTableJPanel);
frame.setVisible(true);
jXTreeTableJPanel.expandRoot();
}
});
}catch(Exception e){
e.printStackTrace();
}
}

}

[/code]

ramswaroop123
Offline
Joined: 2011-11-29
Points: 0

hi pitoniak, I am trying to make treetablenode editable. please tell me what changes to the above code to make treenodes editable..

Thnks

swaroop

kschaefe
Offline
Joined: 2006-06-08
Points: 0

This thread is from 2008.  Perhaps you should create a new thread to post your question, including a small, runnable demo of the problem.

Karl

pitoniak
Offline
Joined: 2008-09-09
Points: 0

i have spent the entire day trying everything that Karl suggested and i just can't get it to work. could someone post the edited code with Karl's suggestions if they get it to work....i am at a loss here :(

thx,

mike

kschaefe
Offline
Joined: 2006-06-08
Points: 0

I don't normally do this, but here's your code working. I don't experience any problems with it from a rendering angle. Can you please explain your issues?

Karl

[code]import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Date;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.TableColumn;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate.ColumnHighlightPredicate;
import org.jdesktop.swingx.treetable.AbstractMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;

public class JXTreeTableJPanel extends JPanel implements ActionListener,
TableModelListener, TreeSelectionListener {
// private static org.apache.log4j.Logger logger = org.apache.log4j.Logger
// .getLogger(JXTreeTableJPanel.class);

private JXTTreeTableNode rootJXTTreeTableNode = null;

private MyTreeTableModel demoTreeTableModel = null;

private JXTreeTable jXTreeTable = null;

public JXTreeTableJPanel() {
GridBagConstraints gridBagConstraints = null;
rootJXTTreeTableNode = new JXTTreeTableNode("root", "test", true, 1);
demoTreeTableModel = new MyTreeTableModel(rootJXTTreeTableNode);
jXTreeTable = new JXTreeTable(demoTreeTableModel);
jXTreeTable.setRootVisible(true);
jXTreeTable.getTableHeader().setReorderingAllowed(false);
TableColumn column = jXTreeTable.getColumn("Count");
JComboBox combo = new JComboBox();
combo.addItem(1);
combo.addItem(2);
column.setCellEditor(new DefaultCellEditor(combo));

// TODO broke??
jXTreeTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

TableColumn t_constraintColumn = jXTreeTable.getColumnModel()
.getColumn(5);

jXTreeTable.addHighlighter(new AlignmentHighlighter(
AlignmentHighlighter.CENTER, new ColumnHighlightPredicate(5)));

jXTreeTable.addMouseListener(new JXTreeTablePopupMenuListener(this));

jXTreeTable.getModel().addTableModelListener(this);
jXTreeTable.addTreeSelectionListener(this);

// jXTreeTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

// entry

// Setup Highlighters...
Highlighter myHighlighter = new ColorHighlighter(
HighlightPredicate.ROLLOVER_ROW, Color.lightGray, Color.red);
jXTreeTable.addHighlighter(myHighlighter);

this.setLayout(new GridBagLayout());

JScrollPane jXTreeTableJTableJscrollPane = new JScrollPane(jXTreeTable);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 1;
gridBagConstraints.gridheight = 1;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.anchor = GridBagConstraints.WEST;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(0, 0, 0, 0);// int top, int left,
// int bottom, int
// right
gridBagConstraints.ipadx = 0;
gridBagConstraints.ipady = 0;
this.add(jXTreeTableJTableJscrollPane, gridBagConstraints);
}

public JXTTreeTableNode addTreeNode(JXTTreeTableNode parent, String name,
boolean enabled) {
JXTTreeTableNode jXTTreeTableNode = null;

parent = parent == null ? rootJXTTreeTableNode : parent;
jXTTreeTableNode = new JXTTreeTableNode(name, name, enabled, 2);
demoTreeTableModel.insertNodeInto(jXTTreeTableNode, parent, parent
.getChildCount());

return jXTTreeTableNode;
}

public void expandRoot() {
jXTreeTable.expandPath(new TreePath(rootJXTTreeTableNode));
}

public void tableChanged(TableModelEvent tableModelEvent) {
System.out.println("model change");
// ((JXTreeTable)tableModelEvent.getSource()).updateUI();
}

public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
TreePath treePath = treeSelectionEvent.getPath();
if (treePath != null) {
JXTTreeTableNode jXTTreeTableNode = (JXTTreeTableNode) treePath
.getLastPathComponent();
System.out.println("TreeSelectionEvent: "
+ jXTTreeTableNode.getName());
}
}

public void actionPerformed(ActionEvent actionEvent) {
try {
TreePath treePath = jXTreeTable.getTreeSelectionModel()
.getSelectionPath();
JXTTreeTableNode treeNode = (JXTTreeTableNode) treePath
.getLastPathComponent();
if (actionEvent.getActionCommand().equals(MyConstants.ADD_TREENODE)) {
String nodeName = JOptionPane
.showInputDialog(this, "Node Name");
addTreeNode(treeNode, nodeName, false);
jXTreeTable.expandPath(treePath);
} else if (actionEvent.getActionCommand().equals(
MyConstants.DELETE_TREENODE)) {
demoTreeTableModel.removeNodeFromParent(treeNode);
}
} catch (Exception e) {
// logger.error(e, e);
}
}

private static class JXTTreeTableNode extends AbstractMutableTreeTableNode {
private String name = null;

private String column1 = null;

private boolean enabled = false;

private boolean divisible = false;

private int count = 0;

public JXTTreeTableNode(String name, String column1, boolean enabled,
int count) {
super(name);
this.name = name;
this.column1 = column1;
this.enabled = enabled;
this.count = count;
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public int getColumnCount() {
return 6;
}

/**
* {@inheritDoc}
*/
@Override
public boolean isEditable(int column) {
switch (column) {
case 0:
return true;
case 3:
return false;
default:
return true;
}
}

public Object getValueAt(int arg0) {
switch (arg0) {
case 0:
return getName();
case 1:
return getColumn1();
case 2:
return isDivisible();
case 3:
return new Date(hashCode());
case 4:
return isEnabled();
case 5:
return getCount();
}

return null;
}

public void setValueAt(Object value, int column) {
switch (column) {
case 0:
setName((String) value);
break;

case 1:
setColumn1((String) value);
break;

case 2:
setDivisible((Boolean) value);
break;
case 4:
setEnabled((Boolean) value);
break;
case 5:
setCount((Integer) value);
break;

// other cases
default:

}
}

public boolean isDivisible() {
return divisible;
}

public void setDivisible(boolean divisible) {
this.divisible = divisible;
}

public String getColumn1() {
return column1;
}

public void setColumn1(String column1) {
this.column1 = column1;
}

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String toString() {
return name;
}
}

private static class MyTreeTableModel extends DefaultTreeTableModel {

public MyTreeTableModel(JXTTreeTableNode jXTTreeTableNode) {
super(jXTTreeTableNode, Arrays.asList("TableName", "Column1 Title",
"Column2 Title", "Column3 Title", "Enabled", "Count"));
}

/**
* {@inheritDoc}
*/
@Override
public Class getColumnClass(int column) {
switch (column) {
case 0:
return String.class;
case 1:
return String.class;
case 2:
return Boolean.class;
case 3:
return Date.class;
case 4:
return Boolean.class;
case 5:
return Integer.class;
default:
return Object.class;
}
}
}

/*
* mousePressed() occurs when the user presses the mouse button.
* mouseReleased() occurs when the user releases the mouse button.
* mouseClicked() occurs when the user presses and releases the mouse
* button. A user normally clicks the mouse button when selecting or double
* clicking an icon. (A double click is two mouse clicks in succession.) A
* mouse action will not result in a click if the user moves the mouse
* before releasing the button. Since a mouse click is the combination of
* pressing and releasing the mouse button, before the event is dispatched
* to the mouseClicked() method, the mousePressed() and mouseReleased()
* methods will both be called. mouseEntered() occurs when the mouse leaves
* its current component and enters the component you are listening to.
* mouseExited() occurs when the mouse leaves the component you are
* listening to. This event occurs the instant the mouse pointer no longer
* resides over the component. mouseDragged() occurs when the user presses
* the mouse button and moves the mouse before releasing the button.
* Releasing the mouse button after a mouseDragged() will not result in a
* mouseClicked(). mouseMoved() occurs when the mouse moves within the
* component without being dragged.
*/
private class JXTreeTablePopupMenuListener extends MouseAdapter {
ActionListener actionListener = null;

public JXTreeTablePopupMenuListener(ActionListener actionListener) {
this.actionListener = actionListener;
}

// Invoked when the mouse cursor has been moved onto a component
// but no buttons have been pushed.
public void mouseMoved(MouseEvent e) {

}

// On some platforms, mouseReleased sets PopupTrigger.
public void mouseReleased(MouseEvent e) {
if (e.isMetaDown()) {
int row = jXTreeTable.rowAtPoint(new Point(e.getX(), e.getY()));
if (row != -1) {
jXTreeTable.setRowSelectionInterval(row, row);
}
}
checkPopup(e);
}

// And on other platforms, mousePressed sets PopupTrigger.
public void mousePressed(MouseEvent e) {
checkPopup(e);
}

/*
* The exact gesture that should bring up a popup menu varies by look
* and feel. In Microsoft Windows, the user by convention brings up a
* popup menu by releasing the right mouse button while the cursor is
* over a component that is popup-enabled. In the Java look and feel,
* the customary trigger is either pressing the right mouse button (for
* a popup that goes away when the button is released) or clicking it
* (for a popup that stays up). In a future release, a new mechanism for
* automatically triggering popup menus in the appropriate way for the
* look and feel might be added.
*/
private void checkPopup(MouseEvent e) {
JPopupMenu jTreePopupMenu = null;
JMenuItem menuItem = null;

// e.isPopupTrigger() Returns whether or not this mouse
// event is the popup menu trigger event for the platform.
if (e.isPopupTrigger()) {
jTreePopupMenu = new JPopupMenu();

menuItem = new JMenuItem(MyConstants.ADD_TREENODE);
menuItem.addActionListener(actionListener);
jTreePopupMenu.add(menuItem);

TreePath treePath = jXTreeTable.getTreeSelectionModel()
.getSelectionPath();
JXTTreeTableNode treeNode = (JXTTreeTableNode) treePath
.getLastPathComponent();
if (!treeNode.equals(rootJXTTreeTableNode)) {
menuItem = new JMenuItem(MyConstants.DELETE_TREENODE);
menuItem.addActionListener(actionListener);
jTreePopupMenu.add(menuItem);
}
jTreePopupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
}

/**
*
* @author Martin Miller
*/
private class AlignmentHighlighter extends AbstractHighlighter implements
SwingConstants {
public int alignment;

public AlignmentHighlighter(int alignment) {
this(alignment, null);
}

public AlignmentHighlighter(int alignment, HighlightPredicate predicate) {
super(predicate);
this.alignment = alignment;
}

protected Component doHighlight(Component renderer,
ComponentAdapter adapter) {
applyAlignment(renderer, adapter);
return renderer;
}

protected void applyAlignment(Component renderer,
ComponentAdapter adapter) {
((JLabel) renderer).setHorizontalAlignment(alignment);
}
}

private class MyConstants {
public static final String ADD_TREENODE = "Add";

public static final String DELETE_TREENODE = "Delete";
}

public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setSize(600, 400);
JXTreeTableJPanel jXTreeTableJPanel = new JXTreeTableJPanel();
jXTreeTableJPanel.addTreeNode(null, "name", true);
frame.setContentPane(jXTreeTableJPanel);
frame.setVisible(true);
jXTreeTableJPanel.expandRoot();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}

}[/code]

pitoniak
Offline
Joined: 2008-09-09
Points: 0

Karl,

Thanks so much. I appologize for the inconvenience. My problem was that i had some code left in the incorrect model, and it was creating the bad behaviour. once it all went into the treenode all was well.

thanks again.

mike

kschaefe
Offline
Joined: 2006-06-08
Points: 0

First, please wrap code in [[b][/b]code]..[[b][/b]/code] tags.
Second, your demo does not compile because JXTreeTableJPanelConstants is missing. It also sounds like it's similar in function to SwingConstants. Please review Effective Java to discover why that's a bad idea.
Third, the edits fail to save because you are not saving them. Your model should implement setValueAt. Since you're using (extending) the default model, the place that you need to add the setValueAt is in the node.
Fourth, I consider it bad practice to extend DefaultTreeTableModel, it was not designed for extension.

Karl

pitoniak
Offline
Joined: 2008-09-09
Points: 0

Karl,

i want to thank you greatly for your assistance; it not only got me unjammed after 3 days; but also i learned how to declare constants correctly. would you mind looking at this updated code and tell me if it looks ok. i want to be sure i used the apporpriate techniques, as we are going to use this control in a solution soon.

also, i have two questions remaining....

1) if i edit the treenode displayed node name text i am udating the userObject, but it is not reflected in the ui. how do i get the ui to update from within the TreeTableModel at the setValueAt method when this change happens?

2) how do i change the size of the columns to make tree colum bigger.

so many thanks. i think this demo will help many people, as it combines combobox editors, and other interesting functions. hopefully others will fix my code to be better and repost.

many thanks again....

mike

[code]

import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Date;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.TableColumn;
import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate.ColumnHighlightPredicate;
import org.jdesktop.swingx.treetable.AbstractMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;

public class JXTreeTableJPanel extends JPanel implements ActionListener, TableModelListener, TreeSelectionListener{
private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(JXTreeTableJPanel.class);
private JXTTreeTableNode rootJXTTreeTableNode = null;
private DemoTreeTableModel demoTreeTableModel = null;
private JXTreeTable jXTreeTable = null;

public JXTreeTableJPanel(){
GridBagConstraints gridBagConstraints = null;
rootJXTTreeTableNode = new JXTTreeTableNode("root", "test", true, 1);
demoTreeTableModel = new DemoTreeTableModel(rootJXTTreeTableNode);
jXTreeTable = new JXTreeTable(demoTreeTableModel);
jXTreeTable.setRootVisible(true);
jXTreeTable.getTableHeader().setReorderingAllowed(false);
TableColumn column = jXTreeTable.getColumn("Count");
JComboBox combo = new JComboBox();
combo.addItem(1);
combo.addItem(2);
column.setCellEditor(new DefaultCellEditor(combo));

TableColumn t_constraintColumn = jXTreeTable.getColumnModel().getColumn(5);

jXTreeTable.addHighlighter(new AlignmentHighlighter(AlignmentHighlighter.CENTER,
new ColumnHighlightPredicate(5)));

jXTreeTable.addMouseListener(new JXTreeTablePopupMenuListener(this));

jXTreeTable.getModel().addTableModelListener(this);
jXTreeTable.addTreeSelectionListener(this);

//Setup Highlighters...
Highlighter myHighlighter = new ColorHighlighter(
HighlightPredicate.ROLLOVER_ROW, Color.lightGray, Color.red);
jXTreeTable.addHighlighter(myHighlighter);

this.setLayout(new GridBagLayout());

JScrollPane jXTreeTableJTableJscrollPane = new JScrollPane(jXTreeTable);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 1;
gridBagConstraints.gridheight = 1;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.anchor = GridBagConstraints.WEST;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(0,0,0,0);//int top, int left, int bottom, int right
gridBagConstraints.ipadx = 0;
gridBagConstraints.ipady = 0;
this.add(jXTreeTableJTableJscrollPane, gridBagConstraints);
}

public JXTTreeTableNode addTreeNode(JXTTreeTableNode parent, String name, boolean enabled){
JXTTreeTableNode jXTTreeTableNode = null;

parent = parent==null ? rootJXTTreeTableNode : parent;
jXTTreeTableNode = new JXTTreeTableNode(name, "test", enabled, 2);
demoTreeTableModel.insertNodeInto(jXTTreeTableNode, parent, parent.getChildCount());

return jXTTreeTableNode;
}

public void expandRoot(){
jXTreeTable.expandPath(new TreePath(rootJXTTreeTableNode));
}

public void tableChanged(TableModelEvent ableModelEvent) {
System.out.println("model change");
}

public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
TreePath treePath = treeSelectionEvent.getPath();
if(treePath != null){
JXTTreeTableNode jXTTreeTableNode = (JXTTreeTableNode)treePath.getLastPathComponent();
System.out.println("TreeSelectionEvent: "+ jXTTreeTableNode.getName());
}
}

public void actionPerformed(ActionEvent actionEvent) {
try{
TreePath treePath = jXTreeTable.getTreeSelectionModel().getSelectionPath();
JXTTreeTableNode treeNode =(JXTTreeTableNode)treePath.getLastPathComponent();
if (actionEvent.getActionCommand().equals(MyConstants.ADD_TREENODE)){
addTreeNode(treeNode, "test_xxx", false);
jXTreeTable.expandPath(treePath);
}else if (actionEvent.getActionCommand().equals(MyConstants.DELETE_TREENODE)){
demoTreeTableModel.removeNodeFromParent(treeNode);
}
}catch(Exception e){
logger.error(e, e);
}
}

private static class JXTTreeTableNode extends AbstractMutableTreeTableNode {
private String name = null;
private String column1 = null;
private boolean enabled = false;
private boolean divisible = false;
private int count = 0;

public JXTTreeTableNode(String name, String column1, boolean enabled, int count){
super(name);
this.name = name;
this.column1 = column1;
this.enabled = enabled;
this.count = count;
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled){
this.enabled = enabled;
}

public int getColumnCount() {
// TODO Auto-generated method stub
return 0;
}

public Object getValueAt(int arg0) {
// TODO Auto-generated method stub
return null;
}

public boolean isDivisible() {
return divisible;
}

public void setDivisible(boolean divisible) {
this.divisible = divisible;
}

public String getColumn1() {
return column1;
}

public void setColumn1(String column1) {
this.column1 = column1;
}

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

private static class DemoTreeTableModel extends DefaultTreeTableModel {

public DemoTreeTableModel(JXTTreeTableNode jXTTreeTableNode) {
super(jXTTreeTableNode);
}

/**
* {@inheritDoc}
*/
@Override
public Object getValueAt(Object node, int column) {
JXTTreeTableNode jXTreeTableNode = (JXTTreeTableNode) node;

Object o = jXTreeTableNode.getUserObject();

switch (column) {
case 0:
return o.toString();
case 1:
return jXTreeTableNode.getColumn1();
case 2:
return jXTreeTableNode.isDivisible();
case 3:
return new Date(o.hashCode());
case 4:
return jXTreeTableNode.isEnabled();
case 5:
return jXTreeTableNode.getCount();
}
return super.getValueAt(node, column);
}

/*
*
* First, please wrap code in [code]..[/code] tags.
Second, your demo does not compile because JXTreeTableJPanelConstants is missing. It also sounds like it's similar in function to SwingConstants. Please review Effective Java to discover why that's a bad idea.
Third, the edits fail to save because you are not saving them. Your model should implement setValueAt. Since you're using (extending) the default model, the place that you need to add the setValueAt is in the node.
Fourth, I consider it bad practice to extend DefaultTreeTableModel, it was not designed for extension.

Karl

*/

public void setValueAt(Object value, Object node, int column) {
super.setValueAt(value,node,column);

JXTTreeTableNode jXTreeTableNode = (JXTTreeTableNode) node;
Object o = jXTreeTableNode.getUserObject();

System.out.println("setValue column: " + column);
switch (column) {

case 0:
jXTreeTableNode.setName((String)value);
break;

case 1:
jXTreeTableNode.setColumn1((String)value);
break;

case 2:
jXTreeTableNode.setDivisible((Boolean)value);
break;
case 4:
jXTreeTableNode.setEnabled((Boolean)value);
break;
case 5:
jXTreeTableNode.setCount((Integer)value);
break;

//other cases
default:

}
}

/**
* Tells if a column can be edited.
*/
public boolean isCellEditable(Object node, int column) {
switch (column) {
case 3:
return false;
default:
return true;
}
}

/**
* {@inheritDoc}
*/
@Override
public Class getColumnClass(int column) {
switch (column) {
case 0:
return String.class;
case 1:
return String.class;
case 2:
return Boolean.class;
case 3:
return Date.class;
case 4:
return Boolean.class;
case 5:
return Integer.class;
default:
return Object.class;
}
}

/**
* {@inheritDoc}
*/
@Override
public int getColumnCount() {
return 6;
}

/**
* {@inheritDoc}
*/
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "TableName";
case 1:
return "Column1 Title";
case 2:
return "Column2 Title";
case 3:
return "Column3 Title";
case 4:
return "Enabled";
case 5:
return "Count";

default:
return "Column " + (column + 1);
}
}
}

/*mousePressed() occurs when the user presses the mouse button.
mouseReleased() occurs when the user releases the mouse button.
mouseClicked() occurs when the user presses and releases the mouse button. A user
normally clicks the mouse button when selecting or double clicking an icon.
(A double click is two mouse clicks in succession.) A mouse action will not result in a
click if the user moves the mouse before releasing the button.
Since a mouse click is the combination of pressing and releasing the mouse button, before
the event is dispatched to the mouseClicked() method, the mousePressed() and mouseReleased()
methods will both be called.
mouseEntered() occurs when the mouse leaves its current component and enters the component
you are listening to.
mouseExited() occurs when the mouse leaves the component you are listening to. This event
occurs the instant the mouse pointer no longer resides over the component.
mouseDragged() occurs when the user presses the mouse button and moves the mouse before
releasing the button. Releasing the mouse button after a mouseDragged() will not result
in a mouseClicked().
mouseMoved() occurs when the mouse moves within the component without being dragged.*/
private class JXTreeTablePopupMenuListener extends MouseAdapter {
ActionListener actionListener = null;

public JXTreeTablePopupMenuListener(ActionListener actionListener){
this.actionListener = actionListener;
}

//Invoked when the mouse cursor has been moved onto a component
//but no buttons have been pushed.
public void mouseMoved(MouseEvent e){

}

//On some platforms, mouseReleased sets PopupTrigger.
public void mouseReleased(MouseEvent e){
if(e.isMetaDown()){
int row = jXTreeTable.rowAtPoint(new Point(e.getX(), e.getY()));
if(row != -1){
jXTreeTable.setRowSelectionInterval(row, row);
}
}
checkPopup(e);
}

//And on other platforms, mousePressed sets PopupTrigger.
public void mousePressed(MouseEvent e){
checkPopup(e);
}

/*The exact gesture that should bring up a popup menu varies by look
and feel. In Microsoft Windows, the user by convention brings up a
popup menu by releasing the right mouse button while the cursor is
over a component that is popup-enabled. In the Java look and feel,
the customary trigger is either pressing the right mouse button
(for a popup that goes away when the button is released) or clicking
it (for a popup that stays up). In a future release, a new mechanism
for automatically triggering popup menus in the appropriate way for
the look and feel might be added.*/
private void checkPopup(MouseEvent e){
JPopupMenu jTreePopupMenu = null;
JMenuItem menuItem = null;

//e.isPopupTrigger() Returns whether or not this mouse
//event is the popup menu trigger event for the platform.
if (e.isPopupTrigger()){
jTreePopupMenu = new JPopupMenu();

menuItem = new JMenuItem(MyConstants.ADD_TREENODE);
menuItem.addActionListener(actionListener);
jTreePopupMenu.add(menuItem);

TreePath treePath = jXTreeTable.getTreeSelectionModel().getSelectionPath();
JXTTreeTableNode treeNode =(JXTTreeTableNode)treePath.getLastPathComponent();
if(!treeNode.equals(rootJXTTreeTableNode)){
menuItem = new JMenuItem(MyConstants.DELETE_TREENODE);
menuItem.addActionListener(actionListener);
jTreePopupMenu.add(menuItem);
}
jTreePopupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
}

/**
*
* @author Martin Miller
*/
private class AlignmentHighlighter extends AbstractHighlighter implements SwingConstants {
public int alignment;

public AlignmentHighlighter(int alignment) {
this(alignment, null);
}

public AlignmentHighlighter(int alignment, HighlightPredicate predicate) {
super(predicate);
this.alignment = alignment;
}

protected Component doHighlight(Component renderer, ComponentAdapter adapter) {
applyAlignment(renderer, adapter);
return renderer;
}

protected void applyAlignment(Component renderer, ComponentAdapter adapter) {
((JLabel)renderer).setHorizontalAlignment(alignment);
}
}

private class MyConstants{
public static final String ADD_TREENODE = "Add";
public static final String DELETE_TREENODE = "Delete";
}

public static void main(String[] args) {
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setSize(600, 400);
JXTreeTableJPanel jXTreeTableJPanel = new JXTreeTableJPanel();
jXTreeTableJPanel.addTreeNode(null, "name", true);
frame.setContentPane(jXTreeTableJPanel);
frame.setVisible(true);
jXTreeTableJPanel.expandRoot();
}
});
}catch(Exception e){
e.printStackTrace();
}
}

}

[/code]

kschaefe
Offline
Joined: 2006-06-08
Points: 0

Mike,

> 1) if i edit the treenode displayed node name text i am udating the userObject,
> but it is not reflected in the ui. how do i get the ui to update from within the
> TreeTableModel at the setValueAt method when this change happens?

You overrode the wrong setValueAt. There is one in the model and one in the node. Place the following (from the model) into the node:
[code]public void setValueAt(Object value, int column) {
switch (column) {

case 0:
setName((String) value);
break;

case 1:
setColumn1((String) value);
break;

case 2:
setDivisible((Boolean) value);
break;

case 4:
setEnabled((Boolean) value);
break;

case 5:
setCount((Integer) value);
break;

// other cases
default:

}
}[/code]

You should also be overriding the getValueAt in the AbstractMutableTreeTableNode. This is the method that the DefaultTreeTableModel queries when looking for the value. You should not extend DefaultTreeTableModel.

> 2) how do i change the size of the columns to make tree colum bigger.

You can set the initial width via the prototype in TableColumnExt. The user can always manually adjust those values, by dragging the column edge.

Karl