In Javafx 2, how to always draw something on top? - javafx-2

I am using javafx 2.2. I have an circle object which moves as the mouse moves. However, there are new objects on the scene. I want to position this object always on top of the others.
With OPENGL, you just draw this circle LAST in each frame in the rendering loop, but with JavaFX, how can this be achieved?

Most of the time just use Node.toFront()
Invoke node.toFront() on starting to drag the node.
The drawing order of a node is determined by the node's position in the node's parent's ObservableList of children. node.toFront() will move the node to the end of the parent's child list so that it will be the last thing rendered for that parent.
Beware that for some layout types (such as HBox), the order of the node in the parent's child list also determine's the nodes layout position in the list as well as the node's rendering order.
For 3D work alter z order
If you are doing 3D work, then adjusting the z-coordinate of the node can also place the node on top of other nodes.
For cross parent dragging use a stack
If you want to drag the node out of it's parent and into another parent, then you could make the root of the scene a stack, remove the node from it's initial parent, place it at the top of the scene stack, drag it to it's new parent, and on drag finished, remove the node from the scene stack and place it into the appropriate position in it's new parent's child list.

Related

How to force Godot to recalculate control nodes size/position?

Building UI in Godot 3.2.1. Of course I use anchors so UI elements are arranged within the screen automatically according to specified layout. I have UI scale system - nothing fancy - simply change font size (DynamicFont.size). If font size is large enough then some UI nodes may be pushed out of the screen. However, nodes don't return to normal sizes/positions with font size decreasing. The way to fix a mess is to resize game window which is not always an option and doesn't seem like a correct way to handle the issue. So how can I force Godot to recalculate control nodes size/position?
Changing the parent control's minimum size to Vector2(0, 0) after changing the font size might do the trick:
$Control.rect_min_size = Vector2(0, 0)
If it's already set to Vector2(0, 0), you may have to change it twice using call_deferred() for it to work.
In your scene tree, find the top level container that contains all of the elements that you want to recalculate. This would be the lowest common ancestor in the scene tree, in computer science terminology. Now, hide the container, by setting it's 'visible' property to false. Then, add a deferred call to change it's 'visible' property back to true.
var your_container = $".".find_node("your-container")
your_container.visible = false
your_container.call_deferred("set_visible", true)
This seems to cause Godot to recalculate the layout of 'your_container'.
It looks like only CanvasItem derived classes have a 'visible' property, so you would not be able to simply set the 'visible' property on a CanvasLayer, for example.
Fortunately, Containers and Controls both derive from CannvasItem, so this methodology should work fine if your lowest common ancestor node is either a Container or a Control or other CanvasItem derived class instance.
I got this working by emitting a signal from a parent element, which appears to force a refresh:
canvas_item.emit_signal("item_rect_changed")
The problem child got refreshed, and unlike the visibility method, focus was retained.

How to ensure a TreeNode is visible

In my app, I'm trying to make sure the selected treenode is shown, meaning it is expanded all the way down, and also scrolled into view.
How can I programmatically implement this (meaning all the tree node's parent nodes are expanded, and it's scrolled into view)?
A tree node only has a reference to its children, not its parent, and there's no way I could find to scroll the tree to a node.
I have tried to look for ITreeNode.EnsureVisible method or similar, but in vain.

Child window with maximize and close buttons

Still working on learning here ... I'm trying to make an application window (stage) into which I can call child windows. The parent naturally comes with minimize, maximize and close (x) buttons, but when I add a child window I can't move or resize the child, and it does not have the standard three buttons.
Here's code I've been toying with:
// Stage ventasStage = new Stage(); // originally the child was stand alone and had the standard 3 buttons
AnchorPane ventas = (AnchorPane) FXMLLoader.load(Punto_de_Venta.class.getResource("VentasGUI.fxml"));
// Scene ventasScene = new Scene(ventas); //"stage" and "scene" removed to add "getChildren"
home.getChildren().add(ventas);
The getChildren gets my new window to be part of the parent scene, but I cannot get the 3 standard buttons. I assume the buttons are added to a Stage and NOT to an AnchorPane (which is what getChildren is getting here) but getChildren can't be used with a Stage, right? So how do I make a parent with interchangeable children where each child is moveable, resizable and has the standard three buttons (minimize, maximize and close)?
Three buttons correspond to a standart Window (it is provided by OS), and it is Stage. Scene - is an object, which corresponds to scene graph and is a propeerty of stage. So use stage.setScene(..) to set Scene to Stage. Stene has a root node (usually, some kind of layout). And it seems for me, that you should use Scene.setRoot(...) method.
BTW, about Stage: you can use stage.init...() to use different decoration schemas, and different types of modality.

ToolbarLayout for a PolylineConnection's children?

Is there a way to specify a layout for children of a PolylineConnection?
I want to add several Labels to a PolylineConnection at ConnectionLocator.MIDDLE without the use of a container figure for the labels.
Both PolylineConnection and Label have EditParts, and the label's model objects are children of the polyline connection's model objects.
Ideally I want to add all label children of a polyline to ConnectionLocator.MIDDLE in a ToolbarLayout...
What you are trying to do is mix two layouts: on the first hand you want to use a ConnectionLocator.MIDDLE to locate the figures, but on the other hand you want to have the figures at this location to have their own layout.
The only solution you have is to create a figure that uses a ToolbarLayout and locate it in the Polyline using the ConnectionLocator
I've found a way to achieve what I wanted:
Very generally, the first child must be added at ConnectionLocator.MIDDLE, and the rest of the children relative to the child before them with the help of RelativeLocator like this (line would be in a loop over all figure children in connection's edit part):
figure.add(childFigure,
new RelativeLocator((IFigure) figureChildren.get(currentIndex - 1),
0.5,
1.7);
I've written a blog post with more details.

JavaFX – exclude/include parent and all its children from layout dynamically

Background/Context:
I have a HBox as a parent and many child Nodes (Buttons, TextFields, Labels…). The HBox is a child of other container (BorderPane/VBox/Grid)
My questions:
How do I dynamically remove/exclude the parent (HBox) and all its children from layout?
I am looking for some three-state property on Node (like in Microsoft WPF):
Visible – visible and participate in layout
Collapsed – is not visible and do not participate in layout (applies to its children as well)
Hidden – is not visible but participate in layout
http://msdn.microsoft.com/en-us/library/ms590101.aspx
What options does JavaFX offer?
My solutions so far:
hBox.setManaged(false);
this work only for HBox, its children are still present
root.getChildren().remove(hBoxTop);
root.getChildren().add(hBoxTop);
Well, this looks like it could work.., but for example in case of root being BorderPane, once I remove/add and remove the HBox, the space after it remains unused. I already tried requestLayout() but id does not force thr rrot to fill it. Am I missing something? Is it correct approach to this problem?
Edited:
Well, I got this working.
Dynamically removing and adding for this specific case can be achieved by:
Remove:
root.setTop(null);
Add:
root.setTop(hBoxTop);
When I did not call setTop(null) on removal, BorderPane still reserved space for HBox (even after removal from its children).
IMHO: it is not very good model as it is parent-container specific. For example if I change, BorderPane to VBox a I had to change these methods as well. For VBox, remove/add on children collection works but I need to remember index so that HBox appears at same place after calling add.
Using root.setTop(null) is not a good idea because as you say it's specific to BorderPane.
I think the best solution is to use:
root.getChildren().remove(yourPane);
And use layout methods to place your other childrens as you want.
But maybe you should not use a BorderPane in the first place with the behaviors you want in your application.
Notice you can also do root.getChildren().clear() to remove all component and add it again to your layout but differently.

Resources