我需要在JavaFX中创建一个带有3个标签的Layout。每个标签应水平居中。第一个应该放在窗口的1/4处,第二个应该是中间的一半(即垂直居中),第三个应该是向下的3/4。
如果调整窗口大小,标签应保持相对位置。
看起来很简单,但我无法弄清楚如何去做。我尝试使用VBox,但似乎没有办法对垂直放置进行精细控制。然后我看了看AnchorPane,但看不出怎么做。
有人可以通过FXML或以编程方式向我展示一种简单的方法吗?
答案 0 :(得分:3)
您可以使用GridPane
执行此操作(可能还有其他方法)。填充四行一列,并使用RowConstraints
使每行具有相同的高度,并对齐每行底部的标签。使用ColumnConstraints
对象水平居中标签。
SSCCE:
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;
public class LayoutExample extends Application {
@Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
int numRows = 4 ;
for (int i = 0 ; i < numRows ; i++) {
RowConstraints rc = new RowConstraints();
rc.setPercentHeight(100.0 / numRows);
rc.setValignment(VPos.BOTTOM);
root.getRowConstraints().add(rc);
}
ColumnConstraints cc = new ColumnConstraints();
cc.setHalignment(HPos.CENTER);
cc.setPercentWidth(100);
root.getColumnConstraints().add(cc);
for (int row = 0; row < 3 ; row++) {
Label label = new Label("Label "+(row+1));
root.add(label, 0, row);
}
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
答案 1 :(得分:1)
下面的ConstrainedGridPane类有助于实现此目的。 在您的4个标签案例中,您可以像这样扩展它:
public class LabelPane extends ConstrainedGridPane() {
public LabelPane() {
// ... setup you labels
// hgap=0 - 1 column using 100%
super.fixColumnSizes(0,100);
// vgap=5 - 4 columns using 25% each ...
super.fixRowSizes(5, 25,25,25,25);
}
}
ConstrainedGridPane源代码
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.RowConstraints;
/**
* a GridPane with Column and RowConstraints
* @author wf
*
*/
public class ConstrainedGridPane extends GridPane {
/**
* fix the columnSizes to the given column Width
* @param colWidths
*/
public void fixColumnSizes(int hGap,int... colWidths) {
this.setHgap(hGap);
// Setting columns size in percent
for (int colWidth : colWidths) {
ColumnConstraints column = new ColumnConstraints();
column.setPercentWidth(colWidth);
getColumnConstraints().add(column);
}
}
/**
* fix the rowSizes to the given rowHeights
* @param rowHeights
*/
public void fixRowSizes(int vGap,int... rowHeight) {
this.setVgap(vGap);
for (int rowWidth : rowHeight) {
RowConstraints rowc = new RowConstraints();
rowc.setPercentHeight(rowWidth);
getRowConstraints().add(rowc);
}
// grid.setPrefSize(WINDOW_WIDTH, WINDOW_HEIGHT); // Default width and
// height
this.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
}
}
答案 2 :(得分:0)
基于FXML
的方法并使用VBox
代替GridPane
看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
<Label text="Label 1" VBox.vgrow="ALWAYS">
<maxHeight><Double fx:constant="MAX_VALUE" /></maxHeight>
</Label>
<Label text="Label 2" VBox.vgrow="ALWAYS">
<maxHeight><Double fx:constant="MAX_VALUE" /></maxHeight>
</Label>
<Label text="Label 3" VBox.vgrow="ALWAYS">
<maxHeight><Double fx:constant="MAX_VALUE" /></maxHeight>
</Label>
</VBox>
这个代码在SceneBuilder生成时可能不喜欢这样,因为我使用e(fx)clipse内部DSL FXGraph来生成它。
<强> 修改 强>
正如@James_D建议的那样(见下面的评论),这可能不是随时适合的解决方案。所以。对上述FXML
的一个小修改是使用Region
作为&#34;间隔符&#34;围绕Label
。
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
<Region VBox.vgrow="ALWAYS">
<maxHeight><Double fx:constant="MAX_VALUE" /></maxHeight>
</Region>
<Label text="Label 1"/>
<Region VBox.vgrow="ALWAYS">
<maxHeight><Double fx:constant="MAX_VALUE" /></maxHeight>
</Region>
<Label text="Label 2"/>
<Region VBox.vgrow="ALWAYS">
<maxHeight><Double fx:constant="MAX_VALUE" /></maxHeight>
</Region>
<Label text="Label 3"/>
<Region VBox.vgrow="ALWAYS">
<maxHeight><Double fx:constant="MAX_VALUE" /></maxHeight>
</Region>
</VBox>
这应该是一个更灵活的解决方案。