学习JavaFX(二):认识布局有关的类和方法

谈到JavaFX或者说GUI设计,就脱不开布局设计


javafx.scene.layout包

javafx.scene.layout包提供了一系列用于布局的类

AnchorPane
AnchorPanebuilder<B extends AnchorPaneBuilder<B>>
BorderPane
BorderPaneBuilder<B extends BorderPaneBuilder<B>>
ColumnConstraints
ConstraintsBase
FlowPane
FlowPaneBuilder<B extends FlowPaneBuilder<B>>
GridPane
GridPaneBuilder<B etends GridPaneBuilder<B>>
HBox
HBoxBuilder<B extends HBoxBuilder<B>>
Pane
PaneBuilder<B extends RegionBuilder<B>>
RowConstraintsBuilder<B extends StackPaneBuilder<B>>
TilePane
TilePaneBuilder<B extends TilePaneBuilder<B>>
VBox
VBoxBuilder<B extends VBoxBuilder<B>>

下面我们讲的所有类都来自于javafx.scene.layout包(布局包)


javafx.scene.layout.Region类

javafx.scene.layout包下,有一个特殊的类javafx.scene.layout.Region

Region的英文释义:『区域』、『范围』;可以容纳其它结点并被CSS装饰

JavaFX的布局控件和界面元素控件都是继承自javafx.scene.Region


Pane(窗格/面板)

javafx.scene.layout.Pane类继承自javafx.scene.layout.Pane

java.lang.Object
    javafx.scene.Node
        javafx.scene.Parent
            javafx.scene.layout.Region
                javafx.scene.layout.Pane

javafx.scnen.layout.Pane类是其它控件布局的父类,可以将Pane看成一个绝对布局控件,当我们将某个控件放置在Pane当中时,需要指定它的位置(layoutXlayoutY),而当我们将几个控件拖拽到Pane中会自动生成layoutXlayoutY

Pane root = new Pane();
Scene scene = new Scene(root);

通常我们不直接使用Pane类而是使用它的子类


Pane的子类

BorderPane

BorderPane提供了五个放置结点的区域:topbottomleftright、和 center;这些区域的大小是自定义的,你可以不定义它,BorderPane就不回给该区域分配空间

默认情况下,如果窗口比所有区域所需空间还大,多余的空间将被分配给中间区域;如果窗口比所需空间小,区域可能会重叠;重叠是由区域设置的顺序决定的

StackPane

StackPane类的地方在一个背到前面的单栈的内容节点

HBox

HBox水平排列空间,不换行

VBox

VBox垂直排列空间,不换行

FlowPane

FlowPane综合类HBoxVBox的特点,既可以水平,也可以垂直排列

GridPane

GridPane类似于HTML的table布局

还有一些,这里仅作为初步认识


getChildren()方法

既然JavaFX的一个场景中单独的元素叫节点(node),这些结点决定了JavaFX用分层次的树状结构来表示应用用户接口;它即能处理输入也能渲染输出(重申,scene是每个JavaFX应用的起点,它是分层的结点树)

除了根结点外,每一个节点都有一个父结点并且有0到多个子节点(还记得吗?在初始化一个scene时要给构造方法传递一个root结点)

getChildren()方法在Parent类中定义,返回该节点的所有孩子节点的列表

protected ObservableList<Node> getChildren() {
    return children;
}

children属于VetoableListDecorator类,向上转型自ObservableList接口

public interface ObservableList<E> extends List<E>, Observable

StackPane对象可以直接使用getChildren().add()添加新的子结点

package application;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello JavaFX!");
        Button btn = new Button();
        btn.setText("Hello World");

        StackPane root = new StackPane();
        root.getChildren().add(btn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }
}

这里写图片描述

Pane对象的效果是这样的

这里写图片描述

BorderPane就什么也看不见了

这里写图片描述

必须通过setPadding()方法设置padding

public final void setPadding(Insets value) { padding.set(value); }
private ObjectProperty<Insets> padding = new StyleableObjectProperty<Insets>(Insets.EMPTY) {
        // Keep track of the last valid value for the sake of
        // rollback in case padding is set to null. Note that
        // Richard really does not like this pattern because
        // it essentially means that binding the padding property
        // is not possible since a binding expression could very
        // easily produce an intermediate null value.

        // Also note that because padding is set virtually everywhere via CSS, and CSS
        // requires a property object in order to set it, there is no benefit to having
        // lazy initialization here.

        private Insets lastValidValue = Insets.EMPTY;

        @Override public Object getBean() { return Region.this; }
        @Override public String getName() { return "padding"; }
        @Override public CssMetaData<Region, Insets> getCssMetaData() {
            return StyleableProperties.PADDING;
        }
        @Override public void invalidated() {
            final Insets newValue = get();
            if (newValue == null) {
                // rollback
                if (isBound()) {
                    unbind();
                }
                set(lastValidValue);
                throw new NullPointerException("cannot set padding to null");
            } else if (!newValue.equals(lastValidValue)) {
                lastValidValue = newValue;
                insets.fireValueChanged();
            }
        }
    };

通过setXXX(XXX为对应方位)设置对应方位的元素结点

/** 把getChildren().add(btn)改成setCenter(btn) */

这里写图片描述

再举一例(BorderPane)

package application;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class Main extends Application {
  public static void main(String[] args) {
    Application.launch(args);
  }

  @Override
  public void start(Stage primaryStage) {
    primaryStage.setTitle("BorderPane Test");
    BorderPane bp = new BorderPane();
    bp.setPadding(new Insets(10, 20, 10, 20));

    Button btnTop = new Button("Top");
    bp.setTop(btnTop);

    Button btnLeft = new Button("Left");
    bp.setLeft(btnLeft);

    Button btnCenter = new Button("Center");
    bp.setCenter(btnCenter);

    Button btnRight = new Button("Right");
    bp.setRight(btnRight);

    Button btnBottom = new Button("Bottom");
    bp.setBottom(btnBottom);

    Scene scene = new Scene(bp, 300, 200);
    primaryStage.setScene(scene);
    primaryStage.show();
  }
}

这里写图片描述

阅读更多

没有更多推荐了,返回首页