【问题标题】:JavaFX layout based on percentage of window size基于窗口大小百分比的 JavaFX 布局
【发布时间】:2016-04-04 01:03:37
【问题描述】:

我需要在 JavaFX 中创建一个带有 3 个标签的布局。每个标签应水平居中。第一个应放置在窗口下方的 1/4 处,第二个应放置在窗口的一半处(即垂直居中),第三个应放置在窗口下方的 3/4 处。

如果调整窗口大小,标签应保持其相对位置。

看起来很简单,但我不知道该怎么做。我尝试使用 VBox,但似乎没有办法很好地控制垂直放置。然后我查看了 AnchorPane,但不知道如何执行此操作。

有人可以告诉我一种使用 FXML 或以编程方式执行此操作的简单方法吗?

【问题讨论】:

    标签: javafx javafx-8


    【解决方案1】:

    您可以通过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);
        }
    }
    

    【讨论】:

    • 我没有考虑过使用 GridPane,但现在回想起来,这是显而易见的选择。感谢您的帮助。
    • 布局窗格可以让您对定位进行最大程度的控制:JavaFX 相当于 Swing 的 GridBagLayout,如果您使用过 Swing。
    【解决方案2】:

    基于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内部DSLFXGraph来生成它。

    编辑

    正如@James_D 所建议的(见下面的评论),这可能不是任何时候都适合的解决方案。所以。从上面对FXML 的一个小更新是使用Regions 作为Labels 周围的“间隔”。

    <?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>
    

    这应该是一个更灵活的解决方案。

    【讨论】:

    • 我尝试使用VBox,但我认为比例不对。每个LabelVBox 高度的 1/3,并且标签居中,所以顶部标签是屏幕下方的 1/6,而不是 1/4(同样底部标签位于 5/ 6).
    • 你可能是对的。在这种情况下,您需要使用Regions 作为Label 周围的“间隔”。我将相应地更新我的答案并添加此选项。
    【解决方案3】:

    下面的 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);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-08-15
      • 2012-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 2013-09-28
      相关资源
      最近更新 更多