Reputation: 17
I've a HBox with two children (an ImageView and a Text), but under certain conditions i want to hide the text to force HBox to reduce its with.
I already have a technic that consists to bind managedProperty
to visibleProperty
, but it not work as expected because the text force the HBox width to include the text width.
My question is : How can i disable a node collision (on his parent) but not setting managedProperty
to false. (because this property makes it no longer maintained in the right position)
Upvotes: 1
Views: 868
Reputation: 82511
You need to override the computation of the minimal node width for this purpose. If you also want to hide parts of the node outside of the of the bounds, you need to apply a clip
to the layout.
Example:
public class ShrinkableHBox extends HBox {
private final int unshrinkableCount;
public ShrinkableHBox(int unshrinkableCount) {
final Rectangle clip = new Rectangle();
clip.widthProperty().bind(widthProperty());
clip.heightProperty().bind(heightProperty());
setClip(clip);
this.unshrinkableCount = unshrinkableCount;
}
@Override
protected double computeMinWidth(double height) {
Insets insets = getInsets();
height -= insets.getTop() + insets.getBottom();
double width = insets.getLeft() + insets.getRight();
List<Node> children = getManagedChildren();
int unshrinkableCount = Math.min(children.size(), this.unshrinkableCount);
// only consider the first unshrinkableCount children for minWidth computation
if (unshrinkableCount > 1) {
width += getSpacing() * (unshrinkableCount - 1);
}
for (int i = 0; i < unshrinkableCount; i++) {
width += children.get(i).minWidth(height);
}
return width;
}
}
@Override
public void start(Stage primaryStage) {
// custom hbox with 2 resizeable
ShrinkableHBox hbox = new ShrinkableHBox(1);
hbox.getChildren().addAll(
new Rectangle(100, 100, Color.RED),
new Rectangle(100, 100, Color.BLUE)
);
hbox.setOpacity(0.5);
Scene scene = new Scene(new HBox(hbox, new Rectangle(100, 100, Color.GREEN.interpolate(Color.TRANSPARENT, 0.5))));
primaryStage.setScene(scene);
primaryStage.show();
}
Note that simply replacing the Text
node with a Label
could also be a solution, since this allows you to shorten the text with ellipsis, if the space is not sufficient.
Upvotes: 1