JavaFX 最初是由 Oracle 推出的一个用于开发富客户端应用程序的框架,它提供了丰富的用户界面控件、布局容器、3D图形绘制、媒体播放和动画等功能,旨在取代较旧的 Swing 框架。JavaFX 于 2007 年推出,2011 年 10 月发布了2.0 版本。JavaFX 2.0 的一个优点是适用于跨平台,而且可以完全用 Java 语言编写代码。
2014年发布的JDK 8.0就包含了JavaFx 2.0 版本。然而,随着时间的发展和技术的变迁,JavaFx 2.0并未达到预期目标,而且在与其他的技术标准竟争中处于下风。从 JDK 11 开始,Oracle 决定不再将 JavaFX 包含在 JDK 中,如有需要JavaFX必须单独下载和使用。
尽管如此,JavaFX 仍然是一个强大的开发工具,开发者可用它来设计、编写、测试、调试和部署富客户端程序,支持跨平台使用。
我们先来看一个简单的“欢迎使用JavaFX”例程,其源代码如下:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;public class 欢迎使用JavaFX extends Application {@Override public void start(Stage stage) {Text text = new Text(10, 40, "欢迎使用 JavaFX !");text.setFont(new Font(40));Scene scene = new Scene(new Group(text), 400, 100);stage.setTitle("欢迎使用JavaFX");stage.setScene(scene);stage.sizeToScene();stage.show();}public static void main(String[] args) {Application.launch(args);}
}
程序演示结果:
下面再来看一个“3D图像演示”例程,其源代码如下:
/***3D图像演示例程***/
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.*;
import javafx.stage.Stage;
public class Shapes3DViewer extends Application {@Override public void start(Stage stage) { PhongMaterial material = new PhongMaterial(); material.setDiffuseColor(Color.LIGHTGRAY); material.setSpecularColor(Color.rgb(30, 30, 30)); Shape3D[] meshView = new Shape3D[] { new Box(200, 200, 200), new Sphere(100), new Cylinder(100, 200), }; for (int i=0; i!=3; ++i) { meshView[i].setMaterial(material); meshView[i].setTranslateX((i + 1) * 220); meshView[i].setTranslateY(200); meshView[i].setTranslateZ(20); meshView[i].setDrawMode(DrawMode.FILL); meshView[i].setCullFace(CullFace.BACK); }; PointLight pointLight = new PointLight(Color.ANTIQUEWHITE); pointLight.setTranslateX(800); pointLight.setTranslateY(-100); pointLight.setTranslateZ(-1000); Group root = new Group(meshView); root.getChildren().add(pointLight); Scene scene = new Scene(root, 800, 400, true); scene.setFill(Color.rgb(10, 10, 40)); scene.setCamera(new PerspectiveCamera(false)); stage.setTitle("3D图像演示");stage.setScene(scene); stage.show(); } public static void main(String[] args) { Application.launch(args); } }
3D图像演示效果图:
JavaFX提供了丰富的控件来构造所需要的程序界面。JavaFX提供了一种容器控件,即面板Pane来简化解决这个问题,不同类型的面板采用不同的布局策略。我们可以根据实际的需要来选择不同的面板,从而构造出我们所需要的界面。下面就介绍几种常用的面板。
(一) FlowPane面板
它采用的布局管理器实际上就是AWT的FlowLayout:按照控件的添加次序按个摆放,按照从上到下、从左到右的次序摆放。当面板的大小发生变化后,舞台的大小也自动跟着变化,场景的大小也自动跟着调整,并且会重新计算各个控件的位置,重新摆放各个控件的位置。
FlowPane测试例程:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class PaneTest extends Application {public static Pane FlowPaneTest() {FlowPane pane = new FlowPane();pane.setPadding(new Insets(11, 12, 13, 14));//设置控件之间的垂直间隔距离pane.setHgap(5);//设置控件之间的水平间隔距离pane.setVgap(5);Label lbName = new Label("姓名:");TextField tfName = new TextField();Label lbPassword = new Label("密码:");TextField tfPassword = new TextField(); Button okbtn = new Button("递交");pane.getChildren().addAll(lbName,tfName,lbPassword,tfPassword,okbtn);return pane;}@Overridepublic void start(Stage stage) {Pane pane = FlowPaneTest();// 创建场景Scene scene = new Scene(pane, 600, 150);// 设置舞台stage.setScene(scene);stage.setTitle("JavaFX面板演示");stage.show();}public static void main(String[] args) {launch(args);}
}
例程演示结果图一:
当程序主窗口宽度变小时,例程演示结果图二:
(二) GridPane面板
它采用的布局管理器实际上就是AWT中的GridLayout:将整个面板划分为若干个格子,每个格子的大小是一样的,每个格子中可以放置一个控件,类似于网格的形式。
GridPane测试例程:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class PaneTest extends Application {public static Pane FlowPaneTest() {FlowPane pane = new FlowPane();pane.setPadding(new Insets(11, 12, 13, 14));//设置控件之间的垂直间隔距离pane.setHgap(5);//设置控件之间的水平间隔距离pane.setVgap(5);Label lbName = new Label("姓名:");TextField tfName = new TextField();Label lbPassword = new Label("密码:");TextField tfPassword = new TextField(); Button okbtn = new Button("递交");pane.getChildren().addAll(lbName,tfName,lbPassword,tfPassword,okbtn);return pane;}public Pane GridPaneTest() {GridPane pane = new GridPane();pane.setAlignment(Pos.CENTER);pane.setPadding(new Insets(11.5, 12.5, 13.5, 14.5));pane.setHgap(5.5);pane.setVgap(5.5);pane.add(new Button("按钮A"), 0, 0);pane.add(new Button("按钮B"), 1, 0);pane.add(new Button("按钮C"), 0, 1);pane.add(new Button("按钮D"), 1, 1);pane.add(new Button("按钮E"), 0, 2);pane.add(new Button("按钮F"), 1, 2);return pane;}public void BorderPaneTest() {}public void HBoxTest() {}public void VBoxTest() {}@Overridepublic void start(Stage stage) {//Pane pane = FlowPaneTest();Pane pane = GridPaneTest();// 创建场景Scene scene = new Scene(pane, 320, 150);// 设置舞台stage.setScene(scene);stage.setTitle("JavaFX面板演示");stage.show();}public static void main(String[] args) {launch(args);}
}
测试演示结果页面:
(三) BorderPane面板
它采用的布局管理器实际上就是AWT中的BorderLayout:将整个面板划分五个区域,分别是上、下、左、右、中,每个区域可以放置一个控件。
在此我们提供一个综合性的演示例程,它还组合使用了后续将要介绍的“HBox面板”和“VBox面板”,请看源代码:
/***BorderPane演示例程***/
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.Separator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;public class BorderPaneExample extends Application {private BorderPane root;@Overridepublic void start(Stage primaryStage) throws Exception{root = new BorderPane(); root.setTop(getMenu());root.setRight(getRightHBox());root.setBottom(getFooter());root.setLeft(getLeftHBox());root.setCenter(getCenterPane());Scene scene = new Scene(root, 900, 500); primaryStage.setTitle("BorderPane演示");primaryStage.setScene(scene);primaryStage.show(); }private MenuBar getMenu(){MenuBar menuBar = new MenuBar();Menu menuFile = new Menu("文件"); Menu menuEdit = new Menu("编辑");Menu menuHelp = new Menu("帮助"); menuBar.getMenus().addAll(menuFile, menuEdit, menuHelp);return menuBar;}private HBox getRightHBox(){HBox hbox = new HBox();VBox vbox = new VBox(50);vbox.setPadding(new Insets(0, 20, 0, 20));vbox.setAlignment(Pos.CENTER);vbox.getChildren().addAll(new Text("其他提示信息A"), new Text("其他提示信息B"), new Text("其他提示信息C")); hbox.getChildren().addAll(new Separator(Orientation.VERTICAL), vbox); return hbox;}private HBox getLeftHBox(){HBox hbox = new HBox();VBox vbox = new VBox(10);vbox.setPadding(new Insets(10));Text text = new Text("导航");text.setFont(Font.font("Helvetica", FontWeight.BOLD, 20));VBox vboxText = new VBox(10);for (int i = 1; i <= 10; i++){vboxText.getChildren().add(new Text("目录 " + i));} Text text2 = new Text("结束位");text2.setFont(Font.font("Helvetica", FontWeight.BOLD, 20));vbox.getChildren().addAll(text, vboxText, text2); hbox.getChildren().addAll(vbox, new Separator(Orientation.VERTICAL));return hbox;}private VBox getFooter(){VBox vbox = new VBox();HBox hbox = new HBox(20);hbox.setPadding(new Insets(5));hbox.setAlignment(Pos.CENTER);hbox.getChildren().addAll(new Text("状态信息01"), new Text("状态信息02"), new Text("状态信息03")); vbox.getChildren().addAll(new Separator(), hbox);return vbox;}private StackPane getCenterPane(){StackPane stackPane = new StackPane();stackPane.setAlignment(Pos.CENTER);Rectangle rec = new Rectangle(200, 200);rec.setFill(Color.DODGERBLUE);rec.widthProperty().bind(stackPane.widthProperty().subtract(50));rec.heightProperty().bind(stackPane.heightProperty().subtract(50));stackPane.getChildren().addAll(rec);return stackPane;}public static void main(String[] args){Application.launch(args);} }
例程的演示页面:
(四) HBox面板
HBox采用的布局管理器,我称其为行式布局管理器,这种布局管理器是对AWT的FlowLayout做了一些限制,它将所有的控件放在同一行,各控件横向布置,无论有多少个控件都是放在同一行,不允许换行。而AWT的FlowLayout布局管理器当一行放不下时是允许换行的。
HBox面板测试例程:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class PaneTest extends Application {public static Pane FlowPaneTest() {FlowPane pane = new FlowPane();pane.setPadding(new Insets(11, 12, 13, 14));//设置控件之间的垂直间隔距离pane.setHgap(5);//设置控件之间的水平间隔距离pane.setVgap(5);Label lbName = new Label("姓名:");TextField tfName = new TextField();Label lbPassword = new Label("密码:");TextField tfPassword = new TextField(); Button okbtn = new Button("递交");pane.getChildren().addAll(lbName,tfName,lbPassword,tfPassword,okbtn);return pane;}public Pane GridPaneTest() {GridPane pane = new GridPane();pane.setAlignment(Pos.CENTER);pane.setPadding(new Insets(11.5, 12.5, 13.5, 14.5));pane.setHgap(5.5);pane.setVgap(5.5);pane.add(new Button("按钮A"), 0, 0);pane.add(new Button("按钮B"), 1, 0);pane.add(new Button("按钮C"), 0, 1);pane.add(new Button("按钮D"), 1, 1);pane.add(new Button("按钮E"), 0, 2);pane.add(new Button("按钮F"), 1, 2);return pane;}public Pane HBoxTest() {HBox pane = new HBox(15);pane.setPadding(new Insets(15, 15, 15, 15));pane.setStyle("-fx-background-color: blue");pane.getChildren().add(new Button("按钮A"));pane.getChildren().add(new Button("按钮B"));pane.getChildren().add(new Button("按钮C"));pane.getChildren().add(new Button("按钮D"));pane.getChildren().add(new Button("按钮E"));pane.getChildren().add(new Button("按钮F"));return pane;}@Overridepublic void start(Stage stage) {//Pane pane = FlowPaneTest();//Pane pane = GridPaneTest();Pane pane = HBoxTest();// 创建场景Scene scene = new Scene(pane, 320, 150);// 设置舞台stage.setScene(scene);stage.setTitle("JavaFX面板演示");stage.show();}public static void main(String[] args) {launch(args);}
}
例程测试效果图:
当框架窗口足够宽时,显示效果如下 :
当框架窗口宽度不足以显示所有组件时,绝不换行显示,超出窗体部分不可见。其显示效果如下 :
(五) VBox面板
VBox的布局策略与HBox有些类似,不过VBox是将所有的控件放在同一列,各控件纵向布置。
不同面板的布局策略各有特点,在应用开发中,可以根据实际需求选取合适的面板进行布局。很多情形可能需要将多种不同类型的面板组合起来使用,才能符合需求效果。
JavaFx 2.0 还可用Java编程实现音频和视频播放器,下一篇博客:
【多媒体】Java实现MP4和MP3音视频播放器【JavaFX】【音视频播放】