Issue
I noticed that the setAlignment
method for layouts within JavaFX is static. Why is this the case? Doesn't this mean that a single node contained within two layouts of the same class cannot have two different alignments?
For example, I have a node called introText
that I want to align differently within two different BorderPane
objects:
BorderPane rootLayout = new BorderPane();
BorderPane infoLayout = new BorderPane();
Label introText = new Label("Select an Item");
rootLayout.setCenter(introText);
infoLayout.setTop(introText);
BorderPane.setAlignment(introText, Pos.CENTER);
#Now introText is positioned in the centre on both rootLayout and infoLayout.
How can I position introText
as Pos.TOP_LEFT
within infoLayout
and Pos.CENTER
within rootLayout
?
Solution
First, you can't actually run into the problem you describe. A Node
can only appear once in the scene graph. If you add the same node to another parent without removing it from its current parent, then it will be silently removed from its current parent first. So, the answer to:
How can I position
introText
asPos.TOP_LEFT
withininfoLayout
andPos.CENTER
withinrootLayout
?
Is: You can't, because introText
cannot be a child of both infoLayout
and rootLayout
at the same time. Now, it may be that the properties of both BorderPane
will contain the label, but that label will only be in one of their children lists, and only nodes in the children list will be rendered by that parent.
As for why methods like BorderPane#setAlignment(Node,Pos)
are static, that's most likely because:
A
BorderPane
does not have a global alignment (unlike e.g.,HBox
), so it doesn't make sense to have an instancealignment
property defined for it.However, a
BorderPane
can end up with empty space in each of its "sections", and so it makes sense to allow the developer to define the alignment of each individual childNode
to determine how they get positioned in that empty space.But it doesn't make sense for
Node
to have an instancealignment
property either. It's too specific a property for such a widely scoped class.So, they defined a static
setAlignment
method onBorderPane
which takes theNode
to set the alignment for. This keeps the property scoped to theBorderPane
, which is the class that makes uses of it, and associates the value with theNode
instance, not the class.And they made the method static because an instance method would imply the alignment state is stored with the
BorderPane
instance. That's not the case--the alignment state is stored with the givenNode
instance (see below).
These methods work by modifying the properties map that each Node
has. For instance, here's the implementation of BorderPane#setAlignment(Node,Pos)
:
public static void setAlignment(Node child, Pos value) { setConstraint(child, ALIGNMENT, value); }
Which calls this method:
static void setConstraint(Node node, Object key, Object value) { if (value == null) { node.getProperties().remove(key); } else { node.getProperties().put(key, value); } if (node.getParent() != null) { node.getParent().requestLayout(); } }
So, as you can see, although these methods may be static, the state is still associated with a node instance. And yes, if you were to take the node out of one BorderPane
and add it to another, then it would still have the same alignment. You'd have to change the alignment if and as needed.
Answered By - Slaw
Answer Checked By - Robin (JavaFixing Admin)