I have an app that uses a JFace TreeViewer. I have it hooked up to a ContentProvider. Mostly, it works great. However, for some actions, like adding a Node in the middle of a list of Nodes or changing a value which should change the label for a Node, the refresh() call doesn't work. I've tried including the parent Node, say "true" for label update. Nothing works all the time.
I have seen that if I leave a collapsible Node closed and add and then expand, the added Node is shown. But if it's already expanded, no change is shown. If I save my tree info to disk and look, the change is made. It's just the TreeViewer refresh that is not working.
I looked at the inputChanged method in my ContentProvider, but it is only called at the beginning and end of my app execution.
Can anyone help? I've read all the web pages that even hint at an answer and nothing has worked.
The inputChanged() if the contentprovider shouldn't be called during refresh() - it is only called when a setInput() call is made to the tree viewer.
In worst case you could call setInput() with the original input to make your elements refreshed, but it can be too slow for your application.
Basically, when you add a new Node in the middle of the group, you have to refresh the parent node (the node who returns the added element using the getChildren() call), or one of its parents. Basically calling refresh() without any parameters might work for this reason.
So for testing, I suggest that you should call refresh() without any parameters, try, whether it works or not, and if it works, then try to figure out the most specific node that works with your application.
Maybe this is obvious to you, but are you calling the refresh from the UI thread? Specifically try the following:
Display.getCurrent().asyncExec(new Runnable() {
#Override
public void run() {
// TODO Call refresh() here
}
});
There is also a syncExec() method.
Hope this helps!
Did you apply a label decorator to your TreeViewer?
I just edited an entry in my TreeViewer without the LabelDecorator I applied before and update(selectedItem, null) actually applied the update (it did nothing before).
Perhaps it's a jface bug?
[edit] seems you have to use updateLabel() from your DecoratingLabelProvider object.
Unfortunately, nothing I could find resolved this. I ended up closing the file and reopening it to force a "refresh/update". Thanks all for the advice.
For me the add(), update() or remove() functions worked pretty decent, of course it is annoying to do so manualy... but if you call them from your model on a change it should just work fine.
Related
Simplifying, I have this structure
Form {
tab=Container(BoxLayout.y());
other stuff
}
The Form is not scrollable (and it is not supposed to be), tab is.
At some point I want to redraw the Form to keep it up to date with some new info added, and I do that creating a new one and showing it.
But I want to scroll down the Container tab to its predecessor's Y-coordinate.
I can easily save the Y coordinate in a static variable using
scrolledToY=tab.getScrollY();
But I can't find a way to set it back when I create the new form.
setScrollY seems to be protected, and indeed if I try to run the program using it, I get an error
error: setScrollY(int) has protected access in Component
tab.setScrollY(scrolledToY);
What is the correct function to use, instead?
Thanks.
You can use scrollRectToVisible().
FYI you can just modify the container and call revalidate to update the UI. This will prevent a nasty refresh problem you might experience. Also check out InfiniteContainer which might be what you're really looking for.
I've a graph in Jung shown using a JFrame.
After I remove a vertex from the graph,
the shown graph automatically redrawn and presented without the removed vertex.
How can I disable it, so that only when I call the repaint method
the graph would be redrawn ?
Thank you
The simple way to do this is extend your graph by some class and add toRemove() method, where you can signify your vertex to delete in boolean array. And the second method deleteNow() which will use your boolean array and delete your vertexes - it will be alike repaint() now. The second way is add boolean value to your vertex instead of array in your extended class. I can't find any other way. Sorry if it's not helpful.
You haven't really given enough information to be able to advise you precisely, but here are some general observations.
The answer to your question is going to depend in part on how you're removing the vertex: interactively or programmatically.
If it's programmatically, then you'll need to look at the code that calls VisualizationViewer.repaint(). It's been a while since I've looked at that part of the code, but the gist is that something is listening to changes to the graph model and triggering repaints (because this is what users generally want).
If it's interactively, then it's probably on the same thread as your visualization, and you should have a fair amount of control over when repaint() gets called (see the calls in the sample code to VV.repaint()).
Using Apache Batik,
Trying to get the JSVGComponent to update (repaint) after adding a new svg element to the DOM. I know about ALWAYS_DYNAMIC, and that is set. The new element(s) are successfully added to the document, but the only way I can get the component to repaint is to resize the view. Upon resize, the new elements pop (appear) into place. I have also tried to add the elements via a Runnable using the UpdateManager and the RunnableQueue. Again, the elements are successfully added, but don't appear until the component is resized (by resizing the housing frame). I have also tried invoking the repaint via a RunQ Runnable, but that also does not work (tho the repaint is actually called).
I think I may have to actually go into the GVT bridge, but I'd sure rather not.
Help extraordinarily appreciated. Thx.
Almost same problem for me : I had to dynamically modifiy the background of boxes (polygon node).
According to MelodyBibi, it works with setSVGDocument(doc); but the SVG flashes during refresh. It's not very appreciable.
My (better) solution is to call
svgCanvas.getCanvasGraphicsNode().fireGraphicsNodeChangeCompleted();
after modifying the DOM model using polygonElement.setAttribute("fill", "red"); on the appropriate Node.
I also added JSVGCanvas.ALWAYS_DYNAMIC before the first loading of the document.
Now my SVG refreshes in realtime, without blinking.
Hoping this will help you.
You can do
svgCanvas.setDocument(doc);
It's works for an JSVGCanvas, may be it will works for you.
You can also try method :
setSVGDocument(doc);
I found this :
There are two common causes for this. The first is that the JSVGCanvas doesn’t know it’s a dynamic document. Normally Batik detects this by looking for script elements but when you modify the document from Java it can’t tell. So call myJSVGCanvas.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC); before loading the document (with setURI, setDocument, setSVGDocument, etc.).
The second common reason is that the changes aren’t made in the UpdateManager ’s thread. You can run code in the UpdateManager ’s thread with the following: UpdateManager um = JSVGCanvas.getUpdateManager(); um.getUpdateRunnableQueue().invokeLater(Runnable); NOTE: The update manager only becomes available after the first rendering completes. You can be notified when this happens by registering a GVTTreeRendererListener.
But i don't try this yet.
I have this pretty big project that I'm working on, graphic editor, and I've had some big problems working with swing components. However, now I have a programmers worst nightmare, a bug that is happening only some of the times.
If I try to select the elements in my JTree, whether when adding elements, or when selecting them when they are selected in diagram (JInternalFrame), some of them don't get expanded.
My structure is something like this, I have a workspace, containing projects and projects that contain diagrams. Diagrams hold all the elements I have, let's say circles, rectangles and so on, in folders (if they are circles, they are put in circles folder...).
Another thing to know is that I select my elements via setSelectedPath/Paths method of my JTree.
Some of the things that may help understanding what I do and what I tried:
I made sure my nodes know how to get to root. (getTreeModel.getPathToRoot returns good path)
I tried adding paths to trees selection model and to tree directly
I have set the trees expandsSelectedPaths to true
Nodes are selected when I expand my tree manually (they even expand afterwards), until I add new elements of type that caused problems
This happens about once when switching through 5 types of elements, and some stranger things happen when I try to add other type of element after I added one that made problems
I hope someone will know what to do, although I think this is very complicated problem. Please ask anything that may help you help me.
OK, thanks everyone for answering, but I have found a very simple workaround for this problem.
The thing was expanding has no effect if the last path component is leaf, for some reason.
What I did was simply making my leaf nodes return false for isLeaf method, and all my problems went away.
if addWhatever() to JTree firing the correct TreeModelEvent (fireChildAdded(), firePathChanged(), fireChildrenLoaded(), treeStructureChanged())
all changes for GUI would be moved to the BackGround Task(s), please look at SwingWorker or Runnable#Thread (most clear and easiest way), but Runnable#Thread required wrapping all output (Swing methods) to the invokeLater
I'm currently working with JTree, more precisely with CheckBoxTree, an inherited class created by JIDE. I need to find a way to reset the tree, meaning :
Clearing the selection
Erasing the nodes
I tried unsetting the Tree variable, the treeModel, and refreshing the UI, but it doesn't works.
Any ideas ?
Unsetting the variable alone won't help - all that will do is lose your copy of the reference to the JTree object.
What you need to do remove the reference the containing object holds to the JTree - I assume you have it some kind of GridContainer or Layout object - remove it from the parent ojbect and then call updateUI on that object.
For erasing the nodes you should get the tree model and clear it or set a new tree model.
To clear the selection, call clearSelection() on the tree (note that setModel(...) already calls clearSelection() so if you want to do both together, just set a new model and repaint).
Just rebuild the tree at the beginning of each iteration.
Something of this sort
RootNode=new CheckBoxTreeNode("root");
CheckBoxTree= new CheckBoxTree(RootNode);
would do the trick. No need to call updateUI. Hope this help.