英文:
JavaFX rotated Text element layout problem / bounding box resizing problem
问题
摘要
当旋转JavaFX Text元素以实现垂直文本时,Text的边界框似乎没有正确调整大小,这会导致问题。我希望Text的边界框在水平方向上尽可能狭窄。
详情
我正在构建一个简单的y坐标轴。目前,代码如下:
public class SimpleYAxis extends HBox {
public SimpleYAxis(double[] tickValues, String axisLabelText, double tickLength, double rowHeight) {
this.setAlignment(Pos.CENTER);
this.setSnapToPixel(true);
VBox labelContainer = new VBox();
labelContainer.setAlignment(Pos.CENTER);
labelContainer.setStyle("-fx-border-color: lime");
Text axisLabel = new Text(axisLabelText);
axisLabel.setTextAlignment(TextAlignment.CENTER);
axisLabel.setTextOrigin(VPos.CENTER);
axisLabel.setStyle("-fx-font: 18 helvetica;");
axisLabel.setRotate(270);
labelContainer.getChildren().add(axisLabel);
this.getChildren().add(labelContainer);
GridPane axisPane = new GridPane();
for (int yIdx = 0; yIdx < tickValues.length; yIdx++) {
Text tickLabel = new Text(String.format("%.2f", tickValues[yIdx]));
tickLabel.setTextAlignment(TextAlignment.CENTER);
tickLabel.setTextOrigin(VPos.TOP);
axisPane.add(tickLabel, 0, yIdx);
Line tick = new Line(0, tickLength, 10, tickLength);
axisPane.add(tick, 1, yIdx);
axisPane.getRowConstraints().add(new RowConstraints(rowHeight));
}
ColumnConstraints axisColConstr = new ColumnConstraints();
axisColConstr.setFillWidth(false);
axisColConstr.setHalignment(HPos.RIGHT);
axisPane.getColumnConstraints().add(axisColConstr);
Line yAxis = new Line(0, 0, 0, rowHeight * (tickValues.length - 1));
yAxis.setTranslateY(yAxis.getBoundsInLocal().getHeight() / 2);
yAxis.setTranslateX(5);
axisPane.add(yAxis, 1, 0);
this.getChildren().add(axisPane);
}
}
使用以下"应用程序":
public class SimpleYAxisSample extends Application {
public static void main(final String[] args) {
ProcessingProfiler.setVerboseOutputState(true);
Application.launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FlowPane pane = new FlowPane();
pane.setAlignment(Pos.CENTER);
SimpleYAxis axis = new SimpleYAxis(dataLoader.xData(), "LABEL", 10, 50);
pane.getChildren().add(axis);
final Scene scene = new Scene(pane, 1000, 1000);
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setOnCloseRequest(evt -> Platform.exit());
}
}
我得到以下结果(围绕标签的绿色框仅用于可视化目的):
如果我不旋转文本(省略行axisLabel.setRotate(270)
),我得到以下结果:
请注意,绿色框的大小是相同的。
我希望水平尺寸(宽度)的框减小到文本高度。这很重要,因为在实际环境中,我有相当长的标签文本,这会在轴标签和轴刻度之间创建一个非常大的间隙。它们应该靠近。在我应用旋转时,文本的边界框似乎不会调整。我该如何避免这种情况?
另一个复杂之处在于,此轴已集成到布局组件的层次结构中(位于BorderPane的中心的GridPane中的FlowPane中的VBox中)。标签的框不能“溢出”到左侧(比如将文本向右移动但保持框的水平大小),因为该框将覆盖布局层次结构中的其他元素,这些元素将不再对鼠标操作可见。因此,将Text的边界框尽量变窄非常重要,而“平移技巧”并不是真正的选项。
英文:
Summary
When rotating a JavaFX Text element to realize vertical text, the Text's bounding box seems not to be resized properly whic causes problems. I would like to have the Text's bounding box as narrow as possible in the horizontal direction.
Details
I am building a simple y-coordinate-axis. Currently, the code looks like this:
public class SimpleYAxis extends HBox {
public SimpleYAxis(double[] tickValues, String axisLabelText, double tickLength, double rowHeight) {
this.setAlignment(Pos.CENTER);
this.setSnapToPixel(true);
VBox labelContainer = new VBox();
labelContainer.setAlignment(Pos.CENTER);
labelContainer.setStyle("-fx-border-color: lime");
Text axisLabel = new Text(axisLabelText);
axisLabel.setTextAlignment(TextAlignment.CENTER);
axisLabel.setTextOrigin(VPos.CENTER);
axisLabel.setStyle("-fx-font: 18 helvetica;");
axisLabel.setRotate(270);
labelContainer.getChildren().add(axisLabel);
this.getChildren().add(labelContainer);
GridPane axisPane = new GridPane();
for (int yIdx = 0; yIdx < tickValues.length; yIdx++) {
Text tickLabel = new Text(String.format("%.2f", tickValues[yIdx]));
tickLabel.setTextAlignment(TextAlignment.CENTER);
tickLabel.setTextOrigin(VPos.TOP);
axisPane.add(tickLabel, 0, yIdx);
Line tick = new Line(0, tickLength, 10, tickLength);
axisPane.add(tick, 1, yIdx);
axisPane.getRowConstraints().add(new RowConstraints(rowHeight));
}
ColumnConstraints axisColConstr = new ColumnConstraints();
axisColConstr.setFillWidth(false);//
axisColConstr.setHalignment(HPos.RIGHT);
axisPane.getColumnConstraints().add(axisColConstr);
Line yAxis = new Line(0, 0, 0, rowHeight * (tickValues.length - 1));
yAxis.setTranslateY(yAxis.getBoundsInLocal().getHeight() / 2);
yAxis.setTranslateX(5);
axisPane.add(yAxis, 1, 0);
this.getChildren().add(axisPane);
}
}
With the following "application":
public class SimpleYAxisSample extends Application {
public static void main(final String[] args) {
ProcessingProfiler.setVerboseOutputState(true);
Application.launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FlowPane pane = new FlowPane();
pane.setAlignment(Pos.CENTER);
SimpleYAxis axis = new SimpleYAxis(dataLoader.xData(), "LABEL", 10, 50);
pane.getChildren().add(axis);
final Scene scene = new Scene(pane, 1000, 1000);
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setOnCloseRequest(evt -> Platform.exit());
}
}
I get the following result (the green box around the label is only for visualization purpuses):
If I do not turn the Text (omit line "axisLabel.setRotate(270)
") I get the following:
Note that the size of the green box is identical.
What I would like to have is that the horizontal size (width) of the box reduces to the text height. This is important, as I have in real life environments quite long label texts which then create a very large gap between the axis label and the axis ticks. They should be close. It seems to me hat the bounding box of the text does not adjust when I apply a rotation. How can avoid this?
Another complication: this axis is integrated into a hierarchy of layout components (in a GridPane in FlowPane in VBox in the center of a BorderPane). The label's box must not "spill" to the left (say by translating the text to the right but keeping the box horizontal size) as the box than on top other elements in the layout hierarchy which will not be accessible to mouse actions any more. So it is really important to have the Text's bounding box as narrow as possible, "translation tricks" are not really an option.
答案1
得分: 3
将旋转的标签包装在 Group
中,以便在布局计算中使用其变换后的边界。
更改为:
labelContainer.getChildren().add(new Group(axisLabel));
有关更多信息,请参见:
使用 Group
来包装旋转标签后,您的应用程序的输出。可以看到,用于标签父级的布局区域的宽度现在符合标签的旋转边界,而不是原始边界。
英文:
Wrap the rotated label a Group
to use its transformed bounds for layout calculation.
Change:
labelContainer.getChildren().add(axisLabel);
To:
labelContainer.getChildren().add(new Group(axisLabel));
For more info, see:
The output of your app when a Group
is used to wrap the rotated label. It can be seen that the width of the layout area required for the label's parent now conforms to the rotated bounds of the label rather than original bounds.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论