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