Why in JavaFX some controls and layout has "children" property, when other has "items" property for essentailly same purpose? Is there any philosophy behind or may be some technical difference?
The getChildren() method is defined in Parent, and consequently inherited by all subclasses of Parent, including Pane, and Control. The implementation of this method in Parent returns an unmodifiable list of child nodes (so it can be used for navigation through the scene graph, but cannot be used to manipulate what is contained in the parent).
The Pane class, and its subclasses, are designed to allow you to lay out other nodes in the scene graph. So Pane overrides getChildren() to return a modifiable list of these nodes: essentially the functionality of a Pane is to allow you to add nodes to it and remove them later if you need. The Pane subclasses position these nodes in various ways.
The Control class is a subclass of Parent, as controls contain other nodes. (E.g. a ComboBox contains a label or text field (if it's editable), and a button for displaying the drop down list.) Control inherits its getChildren() method from Parent, so it returns an unmodifiable list of the child nodes, but doesn't allow you to change that list (because if you removed nodes from a control, it would no longer behave in the way that control was designed to behave).
Some controls are designed to display other content. Trivially, a Label or Button can have a graphic, which is any node. The API for these classes allows you to change that node (via setGraphic()).
More complex controls allow you to add and remove a collection of nodes, as part of their intended functionality. So for example a SplitPane allows you to add as many nodes as you like, and remove them if you need. However, these are not the only nodes contained in the SplitPane. So the getChildren() method still has its implementation from the superclass: it returns an unmodifiable list of all the child nodes of the split pane: that includes the items you add, and the dividers (and potentially other things too). On the other hand, the getItems() method returns the list of nodes that you are allowed to change: so you can remove an item by calling splitPane.getItems().remove(...) (and the split pane will remove the corresponding divider from its child list as well).
Other complex controls have getItems() methods that might return specific types: e.g. Menu.getItems() returns an ObservableList<MenuItem> (so you can't put a TableView in a menu, you can only put menu items in there). Similarly TabPane.getItems() returns an ObservableList<Tab>.
So in short, the two things have completely different functionality. getChildren() returns the list of child nodes for the parent: it allows you to inspect and navigate the scene graph. Parent subclasses that specifically choose to do so may return a modifiable list, allowing you to use them as general containers.
The getItems() methods that some Control classes define are there to define specific functionality of that particular control. They still have getChildren() methods, which will return a different list.
Related
JavaFX 19,
Apparently we used to be able to move a javafx node to a new parent using parent.getChildren().add(node). However, getChildren is now protected making it inaccessible. I also tried changing its accessibility using trySetAccessible(), but this returns false indicating the method is not capable of being set to accessible. What I'm wondering is how am I supposed to move nodes from one parent to another now that getChildren is no longer available?
For example, if I have a Kotlin method:
fun moveNode( parent: Parent, child: Node) {
//First remove child from current parent
child.parent.getChildren().remove(child)
//Then add child to new parent
parent.getChildren().add(child)
This seems like such a useful action for turning traditional applications into dynamic programs, I'm also curious why JavaFX no longer allows it. Thanks for all the help!
You must have messed up something there. I can't see anything that has been changed here since JavaFX 8. Parent has a protectrd children property and a protected getChildren() method which you cannot directly access from some other class and Pane has a public getChildren() method which can be accessed directly from anywhere.
I think I found an answer, but please somebody fact check me on this. Pane objects (which inherit from Parent and Node) replace the getChildren method with a public version. As far as I can tell, only Pane's have accessible children, and are intended to be used this way. So all I have to do is make sure I am ALWAYS moving nodes to a Pane, instead of Parent like in the example above.
Also looks like getChildren() was replaced with children property.
fun moveNode( parent: Pane, child: Node) {
//First remove child from current parent
child.parent.children.remove(child)
//Then add child to new parent
parent.children.add(child)
Update: According to AI, all these Parent objects have accessible getChildren methods...
Pane (and its subclasses: FlowPane, GridPane, HBox, StackPane, TilePane, VBox)
Group
CustomNode (and its subclasses)
using QGraphicsScene.addWidget(my_parent)
Returns a pointer of the proxy of the my_parent widget in the Qgraphicsscene.
Does the Qgraphicsscene also automatically provide proxies for all the children of my_parent?
Could you call from a child of my_parent to find the corresponding proxy?
I am trying to understand if there is an easy way to keep track of proxies of children of a widget without explicitly adding the children into the scene. I.E. how to retrieve the pointers.
I am aware of the methods to find items of the graphicsscene but am not sure if all children are added as items and would prefer to store my own pointers to the proxy objects.
I have multiple loaded components stacked one top of another.
if One loaded component is overlapping on other component , is there any way we can detect the number of items in the component is overlapped by other component.
visible property is not working in this scenario.
Iterate (recursively) QQuickItem::childItems() in C++ would be one way, as suggested. For event delivery we use QQuickItemPrivate::paintOrderChildItems(), which just sorts the same list by z-order; but it's private API. Alteratively there is QQuickItem::childAt(x, y). dumpItemTree() is for debugging. The docs for that also show you how to visit all items recursively in QML: https://doc-snapshots.qt.io/qt6-dev/qml-qtquick-item.html#dumpItemTree-method
I'm using Javascript to dynamically create a QML component via:
var component = Qt.createComponent(qmlURL)
var item = component.createObject(parentLayout, properties)
In this case, the parentLayout is a ColumnLayout and it always creates the object at the end of the children list (which means it is displayed at the bottom of the column).
How can I specify the index position within the children of where the object is placed, or how can I move it in the children list post instantiation?
(I tried assigning parentLayout.children[i] to no avail)
Use case: I have a large existing multi-level (nested) Menu system that is static, but I'd like insert and remove custom submenu items in the hierarchy in response to external plugins registering/unregistering via a service API. While we could completely re-implement the menu system as a dynamic treeview, that seems overkill just to insert a couple menu subitems dynamically.
I have created a custom item renderer for the tree, i have added some children in create children function, my problem is that sometimes i need to show these children and sometimes i don't, depending on clicking on a button which also i have added at create children, the problem is that i had to create the item even if i don't want it to be visible, and removed it by making visible false, and this costs a lot of memory, i have tried to create it at buttons click listener but when scrolling the child disappears, and it may appear again if i keep scrolling up and down..
i am trying to add the child just when i need it to be visible, is this possible or i have to create it on child creation method?
Typically you do something like this with states. This way the components within the container (in this case your item renderer) are only created when the container enters the given state. The nice thing about taking this approach is that you can remain oblivious to when components need to be created/removed and let the states model handle that for you. Hope that helps.