FlowPanes
和TilePanes
是不錯的布局窗格,如果您想一個接一個地連續地水平或垂直地布局子級,則可以。 它們彼此非常相似,因為它們都將子級布置成列(在水平Flow / TilePane的情況下)并按其寬度或行(在垂直Flow / TilePane的情況下)并在其高度處纏繞。 唯一的主要區別是, TilePane
將所有TilePane
放置在相同大小的圖塊中! 因此,將最大孩子的大小作為TilePane
中每個單獨瓦片的TilePane
。 因此, TilePane
也是一種均等地調整按鈕和其他控件的大小和對齊方式的好方法。 (請參閱我以前的文章《 在VBox或HBox內均等地調整按鈕大小》 )
import java.util.Random;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;/**** Created on: 24.03.2012* @author Sebastian Damm*/
public class FlowPaneAndTilePaneExample extends Application
{private Random random;private VBox root; private FlowPane flowPane;private TilePane tilePane;@Overridepublic void start(Stage primaryStage) throws Exception{ random = new Random();root = new VBox(30);VBox upperVBox = createUpperVBox();VBox lowerVBox = createLowerVBox();fillPanesWithImages();root.getChildren().addAll(upperVBox, lowerVBox);Scene scene = new Scene(root, 800, 600, Color.ANTIQUEWHITE);primaryStage.setTitle("FlowPane and TilePane Example");primaryStage.setScene(scene);primaryStage.show(); }private VBox createUpperVBox(){VBox vbox = new VBox(20);Text textFlowPane = new Text("I am a FlowPane");textFlowPane.setFont(Font.font("Calibri", FontWeight.BOLD, 30));textFlowPane.setUnderline(true);textFlowPane.setEffect(new DropShadow()); VBox.setMargin(textFlowPane, new Insets(10, 0, 0, 10));flowPane = new FlowPane();flowPane.setHgap(5);flowPane.setVgap(5);vbox.getChildren().addAll(textFlowPane, flowPane);VBox.setMargin(vbox, new Insets(10));return vbox;}private VBox createLowerVBox(){VBox vbox = new VBox(20);Text textTilePane = new Text("I am a TilePane");textTilePane.setFont(Font.font("Calibri", FontWeight.BOLD, 30));textTilePane.setUnderline(true); textTilePane.setEffect(new DropShadow());VBox.setMargin(textTilePane, new Insets(10, 0, 0, 10));tilePane = new TilePane();tilePane.setHgap(5);tilePane.setVgap(5);vbox.getChildren().addAll(textTilePane, tilePane);VBox.setMargin(vbox, new Insets(10));return vbox;}private void fillPanesWithImages(){for (int i = 1; i <= 6; i++){int imgSize = random.nextInt(128) + 1;Button bt = new Button(); Image img = new Image(FlowPaneAndTilePaneExample.class.getResourceAsStream("images/person" + i + ".png"), imgSize > 50 ? imgSize : 50, 0, true, false);ImageView view = new ImageView(img);bt.setGraphic(view);flowPane.getChildren().add(bt); Button bt2 = new Button(); Image img2 = new Image(FlowPaneAndTilePaneExample.class.getResourceAsStream("images/person" + i + ".png"), imgSize > 50 ? imgSize : 50, 0, true, false);ImageView view2 = new ImageView(img2);bt2.setGraphic(view2);tilePane.getChildren().add(bt2); } }public static void main(String[] args){Application.launch(args);}
}
這個小應用程序通過將相同的內容放在兩個窗格中來顯示FlowPane
和TilePane
之間的主要區別。 這兩個窗格都將放在另一個VBox
,頂部還有一個附加的Text
。
我假設到目前為止,只有FlowPane,TilePane和圖像加載的代碼才是新手。 如果您在理解此JavaFX代碼時遇到問題,請參閱我以前的示例,從JavaFX 2.0的基礎知識入手。
兩個窗格提供除其他一個setHgap
和setVgap
方法來聲明各列和各行之間的間隔。 為了填充按鈕,我選擇加載一些圖像。
在JavaFX 2.0中,可以使用帶有Image
對象的ImageView
來顯示Image
。 ( 注意:這是javafx.scene.image.Image,而不是java.awt.image!)
然后可以將這樣的ImageView
應用于任何Labeled
對象。 Labeled
是Control
的子類,其中包括Label
和ButtonBase
的抽象父類(這是每種按鈕的基類),它使您可以為每種標簽和按鈕設置圖像。
我的六個按鈕都是128×128像素。 為了向您展示FlowPane
和TilePane
之間的FlowPane
,我選擇了調整這些圖像的大小。 目前,這只能直接在Image
類的構造函數中實現,因為以后沒有任何方法可以更改Image
對象的大小。 一個構造函數使用InputStream
,兩個寬度和高度的雙精度值,和兩個布爾值,用于保留圖像的縱橫比和'?smooth'屬性。 如果要調整圖像大小并保持寬高比,則可以指定寬度或高度,并通過傳遞“ true”作為第一個布爾值來保持寬高比。 使用“平滑”屬性,您可以在更清晰或更快速的圖像渲染之間進行選擇。
根據為該大小生成的隨機值,您的應用程序應如下所示:

您可以看到圖像基本相同。 不同的是,該FlowPane
后直接在另一只通過與規定的間隙隔開,勾畫出所有圖像setHgap
方法,而TilePane
把所有圖像在相同尺寸的瓷磚。
FlowPane和TilePane –示例2
這是另一個小示例:正如本文的引言中所述, TilePane
也是一種均等地調整按鈕大小和對齊方式的好方法。 為了FlowPane
顯示FlowPane
和TilePane
之間的主要區別,將相同的元素再次放置在兩個窗格中。
這是代碼:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Separator;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.RadialGradientBuilder;
import javafx.scene.paint.Stop;
import javafx.scene.text.Font;
import javafx.stage.Stage;/**** Created on: 24.03.2012* @author Sebastian Damm*/
public class FlowPaneAndTilePaneExample2 extends Application
{private VBox root; private FlowPane flowPane;private TilePane tilePane;@Overridepublic void start(Stage primaryStage) throws Exception{ root = new VBox();root.setAlignment(Pos.CENTER);initFlowPane();initTilePane();createButtons();root.getChildren().addAll(flowPane, new Separator(), tilePane);Scene scene = new Scene(root, 400, 300);RadialGradient background = RadialGradientBuilder.create().stops(new Stop(0d, Color.web("#fff")), new Stop(0.47, Color.web("#cbebff")), new Stop(1d, Color.web("#a1dbff"))) .cycleMethod(CycleMethod.NO_CYCLE).build();scene.setFill(background);primaryStage.setTitle("FlowPane and TilePane Example 2");primaryStage.setScene(scene);primaryStage.show(); }private void initFlowPane(){ flowPane = new FlowPane(Orientation.VERTICAL);flowPane.setHgap(5);flowPane.setVgap(5); flowPane.setPrefHeight(200);flowPane.setAlignment(Pos.CENTER);VBox.setMargin(flowPane, new Insets(10));}private void initTilePane(){tilePane = new TilePane(Orientation.VERTICAL);tilePane.setHgap(5);tilePane.setVgap(5);tilePane.setPrefHeight(200);tilePane.setAlignment(Pos.CENTER);VBox.setMargin(tilePane, new Insets(10));}private void createButtons(){Button bt = new Button("1");bt.setMaxWidth(Double.MAX_VALUE);bt.setMaxHeight(Double.MAX_VALUE);Button bt2 = new Button("Button 1");bt2.setMaxWidth(Double.MAX_VALUE);bt2.setMaxHeight(Double.MAX_VALUE);Button bt3 = new Button("Button");bt3.setMaxWidth(Double.MAX_VALUE);bt3.setMaxHeight(Double.MAX_VALUE);bt3.setFont(Font.font("Cambria", 22));Button bt4 = new Button("1");bt4.setMaxWidth(Double.MAX_VALUE);bt4.setMaxHeight(Double.MAX_VALUE);Button bt5 = new Button("Button 1");bt5.setMaxWidth(Double.MAX_VALUE);bt5.setMaxHeight(Double.MAX_VALUE);Button bt6 = new Button("Button");bt6.setMaxWidth(Double.MAX_VALUE);bt6.setMaxHeight(Double.MAX_VALUE);bt6.setFont(Font.font("Helvetica", 22));flowPane.getChildren().addAll(bt, bt2, bt3);tilePane.getChildren().addAll(bt4, bt5, bt6);}public static void main(String[] args){Application.launch(args);}
}
再次根節點是一個VBox
與FlowPane
在上部區域和一個TilePane
在下部區域。 代碼中的某些部分可能對您來說是新的。 首先看一下44-51行。 在這里,我借助JavaFX 2.0中眾多構建器類之一的幫助,為場景的背景創建了一個徑向漸變。 稍后,我將在自己的文章中介紹漸變以及構建器模式,因此在這里我將不做過多解釋。 現在,您只需要知道,這些線會創建一個放射狀的背景,然后通過場景的setFill
方法將其應用于場景。 (就像在前面的示例中一樣,我們可以直接在場景的構造函數中指定背景填充,因為它需要一個Paint
對象,該對象不僅包括普通顏色,還包括各種漸變)。
與第一個示例相反,這次我們使用垂直窗格,其中填充了按鈕。 因為我想允許按鈕增長到其父代提供的任何空間,所以我將每個按鈕的最大高度和最大寬度設置為常量Double.MAX_VALUE
。 (如果您還沒有在VBox或HBox中查看我之前的示例Sizing Buttons,請同樣查看)
您的應用程序應如下所示:

正如你可以在這兩個窗格看到的按鈕長到其父的寬度,但只在TilePane
按鈕也垂直增長,因為在每一個瓦片TilePane
是大小相等。 該示例可能看起來并不很重要,但是直到現在我在JavaFX 2.0中開發的應用程序中,我一直都希望按鈕的大小和對齊方式均等,因為這是一個微妙的方面,它使您的應用程序看起來更加簡潔。
如果您調整窗口大小,則其外觀應如下所示:

請注意,一旦按鈕不再在FlowPane
垂直FlowPane
,按鈕將僅占據其所需的空間(基于其內容),而在TilePane
所有按鈕的大小仍相等。
參考: JavaFX 2.0布局窗格–來自我們JCG合作伙伴 Sebastian Damm的FlowPane和TilePane ,在Java博客Just my 2 cents上。
翻譯自: https://www.javacodegeeks.com/2012/07/javafx-20-layout-panes-flowpane-and.html