【问题标题】:JavaFX setPrefSize is not changing vBox sizeJavaFX setPrefSize 不改变 vBox 大小
【发布时间】:2020-06-21 15:32:14
【问题描述】:

我是 JavaFX 的初学者,我面临这个问题: 我想做这样的布局:What i need

这就是我所拥有的:enter image description here

似乎我尝试了很多不同的布局,但我就是无法做到正确。我最终得到了 VBox'es,这是我能得到的最好的。即使我用“PrefSize”将“vBox2”大小描述为整个场景的一半,但它根本没有反应。

这是我的代码:

    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) {

        // Create a border pane
        BorderPane pane = new BorderPane();

         // Place nodes in the pane
        pane.setLeft(getVBox());
        pane.setBottom(getVBox2());
        pane.setRight(getVBox3());

        // Create a scene and place it in the stage
        Scene scene = new Scene(pane, 1000,800);
        primaryStage.setTitle("ShowHBoxVBox"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage
    }

    private VBox getVBox() {
        VBox vBox = new VBox(15);
        vBox.setPadding(new Insets(15, 5, 5, 5));
        vBox.getChildren().add(new Label("vbox"));

        Label[] courses = {new Label("CSCI 1301"), new Label("CSCI 1302"),
            new Label("CSCI 2410"), new Label("CSCI 3720")};

        for (Label course : courses) {
            VBox.setMargin(course, new Insets(0, 0, 0, 15));
            vBox.getChildren().add(course);
        }
        vBox.setStyle("-fx-border-style: solid inside;");
        vBox.setPrefSize(500, 400);

        return vBox;
    }

    private VBox getVBox2() {
        VBox vBox2 = new VBox(15);
        vBox2.setPadding(new Insets(15, 5, 5, 5));
        vBox2.getChildren().add(new Label("Vbox2"));

        Label[] courses = {new Label("CSCI 1301"), new Label("CSCI 1302"),
            new Label("CSCI 2410"), new Label("CSCI 3720")};

        for (Label course : courses) {
            VBox.setMargin(course, new Insets(5, 5, 5, 15));
            vBox2.getChildren().add(course);
        }
        vBox2.setStyle("-fx-border-style: solid inside;");
        vBox2.setPrefSize(500, 400);

        return vBox2;
    }

    private VBox getVBox3() {
        VBox vBox3 = new VBox(15);
        vBox3.setPadding(new Insets(15, 5, 5, 5));
        vBox3.getChildren().add(new Label("vbox3"));

        Label[] courses = {new Label("CSCI 1301"), new Label("CSCI 1302"),
            new Label("CSCI 2410"), new Label("CSCI 3720")};

        for (Label course : courses) {
            VBox.setMargin(course, new Insets(0, 0, 0, 15));
            vBox3.getChildren().add(course);
        }
        vBox3.setStyle("-fx-border-style: solid inside;");
        vBox3.setPrefSize(500, 800);

        return vBox3;
    }

}

我无法使用 FXML 或在 CSS 中设置样式。

感谢您的任何建议。

【问题讨论】:

    标签: java javafx layout netbeans


    【解决方案1】:

    我能想到的最简单的解决方案是构造两个 HBox 并将 VBox 放入其中。 例如:Sebastian Damm 创建了这个简单的示例: https://www.javacodegeeks.com/2012/07/javafx-20-layout-panes-hbox-and-vbox.html

        import javafx.application.Application;
        import javafx.geometry.Pos;
        import javafx.scene.Scene;
        import javafx.scene.control.Button;
        import javafx.scene.layout.HBox;
        import javafx.scene.layout.VBox;
        import javafx.stage.Stage;
    
    
    /**
     *
     * Created on: 20.03.2012
     * @author Sebastian Damm
     */
    public class HBoxandVBoxExample extends Application
    {
        @Override
        public void start(Stage primaryStage) throws Exception
        {                
            HBox hbox = new HBox(50);
            hbox.setAlignment(Pos.CENTER); // default TOP_LEFT
    
            VBox vbox1 = new VBox();
            vbox1.setAlignment(Pos.BOTTOM_CENTER);
            vbox1.setStyle("-fx-border-style: solid;"
                    + "-fx-border-width: 1;"
                    + "-fx-border-color: black");
    
            VBox vbox2 = new VBox(10);
            vbox2.setAlignment(Pos.CENTER);
            vbox2.setStyle("-fx-border-style: solid;"
                    + "-fx-border-width: 1;"
                    + "-fx-border-color: black");
    
            VBox vbox3 = new VBox(20);
            vbox3.setAlignment(Pos.TOP_CENTER);
            vbox3.setStyle("-fx-border-style: solid;"
                    + "-fx-border-width: 1;"
                    + "-fx-border-color: black");
    
            for (int i = 0; i < 5; i++)
            {
                Button bt = new Button("Button " + (i+1));
                Button bt2 = new Button("Button " + (i+1)); // unfortunately there´s no "clone" or "copy" method
                Button bt3 = new Button("Button " + (i+1));
    
                vbox1.getChildren().add(bt);
                vbox2.getChildren().add(bt2);
                vbox3.getChildren().add(bt3);
            }
    
            hbox.getChildren().addAll(vbox1, vbox2, vbox3);
            Scene scene = new Scene(hbox, 350, 250); // the hbox is the root node
    
            primaryStage.setTitle("HBox and VBox Example");
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args)
        {
            Application.launch(args);
        }
    }
    

    【讨论】:

      【解决方案2】:

      布局窗格(如VBoxBorderPane)布局其子节点的一般流程如下:

      1. 查询子节点的最小值、最大值和首选 尺寸
      2. 计算要分配给每个孩子的位置和大小 节点,坚持自己的布局策略,尽最大努力 尊重子节点的最小、首选和最大大小

      3. 请求子节点执行自己的布局,分配 尺寸计算到每个

      并非总是可以遵守子节点的所有最小/最大/首选项约束;例如如果VBox 的所有子元素的最小高度之和大于VBox 本身的高度,则根本无法将所有子元素放入布局中。相反,如果VBox 的高度大于所有子项的首选高度之和,则会以某种方式分配额外的垂直空间。大多数布局窗格都具有配置如何处理这些情况的设置:其中一些设置适用于整个布局窗格,其他设置适用于每个子级。

      BorderPane 的布局策略基本上如下:

      • topbottom 节点分配了BorderPane 的全部宽度,并且每个节点都获得了它们的首选高度。这些节点位于边框窗格的整个宽度上,分别位于顶部和底部。 这是使BorderPane 的行为与您需要的方式不同的部分。
      • leftright 节点被分配了BorderPane 的完整高度,减去topbottom 节点的高度,并且每个节点都获得了它们的首选宽度。它们分别位于边框窗格的左侧和右侧,位于top 下方和bottom 节点上方。
      • center 节点接收所有剩余空间。

      如果结果大小违反节点的最小或最大大小,则会调整此值。

      所以你的图片中的布局完全符合预期; vbox2 获取全宽及其首选高度; vbox 获取其首选宽度和边框窗格的剩余高度,vbox3 获取剩余空间。

      您基本上可以通过将vboxvbox2 放在它们自己的VBox 中,并将VBox 放在边框窗格的左侧来实现您在此处寻找的内容;然后将vbox3 放在中间(右边也可以):

      import javafx.application.Application;
      import javafx.geometry.Insets;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;
      
      public class Layout extends Application {
          @Override // Override the start method in the Application class
          public void start(Stage primaryStage) {
      
              // Create a border pane
              BorderPane pane = new BorderPane();
      
               // Place nodes in the pane
      
              VBox left = new VBox(getVBox(), getVBox2());
              pane.setLeft(left);
              pane.setCenter(getVBox3());
      
              // Create a scene and place it in the stage
              Scene scene = new Scene(pane);
              primaryStage.setTitle("ShowHBoxVBox"); // Set the stage title
              primaryStage.setScene(scene); // Place the scene in the stage
              primaryStage.show(); // Display the stage
          }
      
          private VBox getVBox() {
              VBox vBox = new VBox(15);
              vBox.setPadding(new Insets(15, 5, 5, 5));
              vBox.getChildren().add(new Label("vbox"));
      
              Label[] courses = {new Label("CSCI 1301"), new Label("CSCI 1302"),
                  new Label("CSCI 2410"), new Label("CSCI 3720")};
      
              for (Label course : courses) {
                  VBox.setMargin(course, new Insets(0, 0, 0, 15));
                  vBox.getChildren().add(course);
              }
              vBox.setStyle("-fx-border-style: solid inside;");
              vBox.setPrefSize(500, 400);
      
              return vBox;
          }
      
          private VBox getVBox2() {
              VBox vBox2 = new VBox(15);
              vBox2.setPadding(new Insets(15, 5, 5, 5));
              vBox2.getChildren().add(new Label("Vbox2"));
      
              Label[] courses = {new Label("CSCI 1301"), new Label("CSCI 1302"),
                  new Label("CSCI 2410"), new Label("CSCI 3720")};
      
              for (Label course : courses) {
                  VBox.setMargin(course, new Insets(5, 5, 5, 15));
                  vBox2.getChildren().add(course);
              }
              vBox2.setStyle("-fx-border-style: solid inside;");
              vBox2.setPrefSize(500, 400);
      
              return vBox2;
          }
      
          private VBox getVBox3() {
              VBox vBox3 = new VBox(15);
              vBox3.setPadding(new Insets(15, 5, 5, 5));
              vBox3.getChildren().add(new Label("vbox3"));
      
              Label[] courses = {new Label("CSCI 1301"), new Label("CSCI 1302"),
                  new Label("CSCI 2410"), new Label("CSCI 3720")};
      
              for (Label course : courses) {
                  VBox.setMargin(course, new Insets(0, 0, 0, 15));
                  vBox3.getChildren().add(course);
              }
              vBox3.setStyle("-fx-border-style: solid inside;");
              vBox3.setPrefSize(500, 800);
      
              return vBox3;
          }
      
          public static void main(String[] args) { Application.launch(args); }
      
      }
      

      您尚未指定您希望它在调整窗口大小时的行为方式,但“中心”区域本质上将比左侧区域更具“响应性”。

      初始窗口如下所示:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-21
        • 2015-10-11
        • 1970-01-01
        • 2017-09-02
        • 2014-12-14
        • 2016-09-03
        • 2016-11-15
        • 1970-01-01
        相关资源
        最近更新 更多