3

I am trying to make a scene editor to go with my rendering engine. I am using swing to make the GUI and also swingx for its JXTreeTable component. Everything is working fine, except that the Scene tree table is not updating the names of the nodes automatically as I would like. For example, in the next image, I change the name of one of the nodes, and nothing seems to happen. However if I then move my mouse over the node in the Scene box (the one at the top) the name gets updated.

enter image description here

I have two JXTreeTable, and two models which extend AbstractTreeTableModel. Here is the relevant code for the Properties model.

public class PropertiesModel extends AbstractTreeTableModel{
    private EE_Property root;
    private SceneModel mSceneModel;
    private EE_SceneObject sceneSelection;

    ...

    @Override
    public void setValueAt(Object value, Object node, int column){
        ((EE_Property)node).setValue((String)value);

        // Updates the values of the current scene selection
        sceneSelection.setProperties(root);

        TreePath path = new TreePath(sceneSelection.getParent());
        int index = mSceneModel.getIndexOfChild(sceneSelection.getParent(), sceneSelection);

        // This is where I thought the updating of the scene model would happen and thus redraw it correctly
        mSceneModel.getTreeModelSupport().fireChildChanged(path, index, sceneSelection);
    }
}

I thought that using fireChildChanged() would update the scene tree table as I wanted.

If I call fireChildChanged() with index=0, I can get the Root node to update when I rename it, but any other index I have to wait till I move the mouse over it to update.

Edit: problem solved

I tried the redraw method suggested by @Shakedown which partially worked but sometimes would leave "..." after the text if the new text was longer than the original.

I did however realize that the problem was coming from the TreePath not being generated properly. When using TreePath path = new TreePath(sceneSelection.getParent());, the path's parent was null, thus not allowing the tree to update. I now use this code which works :

// mTT is the scene tree table
TreePath nodePath = mSceneModel.mTT.getTreeSelectionModel().getSelectionPath(); 
int index = mSceneModel.getIndexOfChild(sceneSelection.getParent(), sceneSelection);
mSceneModel.getTreeModelSupport().fireChildChanged(nodePath.getParentPath(), index, sceneSelection);
NickLH
  • 2,643
  • 17
  • 28
  • glad you found a solution - just beware: this smells a bit as it requires to manually fire a change from the _outside_ of the model itself. The sceneModel should do so itself on detecting a change on the properties of the contained objects – kleopatra Nov 28 '11 at 08:18
  • Yeah, I realized that I am doing it in the wrong way after looking into @Shakedown's comments. But it has still allowed me to get something running and now I can check that my future "correct implementation" works the way I expect. – NickLH Nov 28 '11 at 15:21

1 Answers1

3

You're notifying the listeners of the SceneModel which is not the tree-table that you want to update. Look for some similar fireXXX methods on the AbstractTreeTableModel class and call those, which will notify the JXTreeTable and it will redraw itself.

It looks like the one you want is fireTreeNodesChanged(...), so play around with that and figure out what parameters you need to pass in.

Nate W.
  • 9,141
  • 6
  • 43
  • 65
  • I do want to update the listeners of SceneModel, since this is the table at the top of the screen... Maybe I am not understanding what you are saying, but I thought that this is exactly what I am doing. My PropertiesModel class holds a reference to my SceneModel class (mSceneModel). Since I am calling the fireChildChanged on mSceneModel, shouldn't this do what I want? – NickLH Nov 28 '11 at 03:14
  • Well it depends on which model is being used by the tree-table. I'm assuming that it is in fact an instance of a `PropertiesModel`, in which case the tree-table will be adding listeners to that object, not the `SceneModel` object. – Nate W. Nov 28 '11 at 03:15
  • The top JXTreeTable uses the SceneModel and the bottom JXTreeTable uses the PropertiesModel. Since I change the value from within the PropertiesModel (i.e. I edit something within the bottom tree table), I need to somehow update the SceneModel so that the top tree table gets updated, which is what I thought I was doing. – NickLH Nov 28 '11 at 03:20
  • I see what you're saying. You probably should still notify whoever is listening on the `PropertiesModel` after a value is changed. Have you tried calling `repaint()` on the tree-table after the value changes? I would hope you don't need to, but sometimes the tree-table implementations can be buggy. Also, instead of having the `PropertiesModel` keep a reference to the `SceneModel`, you should link the two of them together with model listeners. So you would add a listener to the `PropertiesModel` and when a tree node changes you would update the `SceneModel`. – Nate W. Nov 28 '11 at 03:37
  • Fixed it! See my edit for how. Thanks for all the help. I marked this answer as accepted since your help lead me to the answer, and for the suggestions in your last comment, which I will try to implement now. It was by checking what was being passed to `fireTreeNodesChanged` by `fireTreeNodeChanged` that I found the mistake. – NickLH Nov 28 '11 at 04:40