JavaFX 基础控件 II
最后修改于 2023 年 10 月 18 日
在本章中,我们将继续介绍基本的 JavaFX 控件。我们将介绍 DatePicker
,MenuBar
,ColorPicker
,RadioButton
和 TabPane
控件。
JavaFX DatePicker
DatePicker
是一个用于选择日期的控件。
package com.zetcode; import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.DatePicker; import javafx.scene.control.Label; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class DatePickerEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new VBox(15); root.setPadding(new Insets(10)); var lbl = new Label("..."); var datePicker = new DatePicker(); datePicker.setOnAction(e -> { var date = datePicker.getValue(); lbl.setText(date.toString()); }); root.getChildren().addAll(datePicker, lbl); var scene = new Scene(root, 350, 200); stage.setTitle("Date picker"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
该示例使用 DatePicker
控件来选择和显示日期。日期显示在标签控件中。
var datePicker = new DatePicker();
创建 DatePicker
控件的实例。
datePicker.setOnAction(e -> { var date = datePicker.getValue(); lbl.setText(date.toString()); });
getValue
方法将选定的日期作为 LocalDate
返回。 选定的日期使用其 setText
方法设置为标签控件。

JavaFX MenuBar
MenuBar
由 Menu
对象组成,这些对象包含 MenuItem
对象 - 应用程序的命令。它传统上放置在应用程序窗口的顶部。
package com.zetcode; import javafx.application.Application; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.layout.HBox; import javafx.stage.Stage; public class MenuBarEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new HBox(); var mbar = new MenuBar(); mbar.prefWidthProperty().bind(stage.widthProperty()); var handler = new MyMenuHandler(); var fileMenu = new Menu("File"); mbar.getMenus().add(fileMenu); var nmi = new MenuItem("New"); nmi.setOnAction(handler); fileMenu.getItems().add(nmi); var omi = new MenuItem("Open"); omi.setOnAction(handler); fileMenu.getItems().add(omi); var smi = new MenuItem("Save"); smi.setOnAction(handler); fileMenu.getItems().add(smi); fileMenu.getItems().add(new SeparatorMenuItem()); var emi = new MenuItem("Exit"); emi.setOnAction((ActionEvent event) -> Platform.exit()); fileMenu.getItems().add(emi); root.getChildren().add(mbar); var scene = new Scene(root, 300, 250); stage.setTitle("MenuBar"); stage.setScene(scene); stage.show(); } private class MyMenuHandler implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent event) { doShowMessageDialog(event); } private void doShowMessageDialog(ActionEvent event) { var mi = (MenuItem) event.getSource(); String item = mi.getText(); var alert = new Alert(AlertType.INFORMATION); alert.setTitle("Information dialog"); alert.setHeaderText("Menu item selection information"); alert.setContentText(item + " menu item selected"); alert.showAndWait(); } } public static void main(String[] args) { launch(args); } }
该示例在菜单栏中包含一个菜单。 菜单包含四个菜单项和一个分隔符。
var mbar = new MenuBar(); mbar.prefWidthProperty().bind(stage.widthProperty());
创建 MenuBar
控件。 在一个水平框中,它足够大以显示其单个菜单。 通过将其绑定到舞台的 widthProperty
,菜单栏从左到右拉伸。
var handler = new MyMenuHandler();
创建菜单处理程序。 它由三个菜单项共享。
var fileMenu = new Menu("File"); mbar.getMenus().add(fileMenu);
创建 File Menu
并将其添加到菜单栏中。
var nmi = new MenuItem("New"); nmi.setOnAction(handler); fileMenu.getItems().add(nmi);
创建 New MenuItem
并将其添加到 File 菜单中。 使用 setOnAction
方法设置菜单项的处理程序。
fileMenu.getItems().add(new SeparatorMenuItem());
SeparatorMenuItem
是一个水平分隔符,用于在视觉上分隔相关的菜单项。
emi.setOnAction((ActionEvent event) -> Platform.exit());
Exit 菜单项使用 Platform.exit
方法调用终止应用程序。
private class MyMenuHandler implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent event) { doShowMessageDialog(event); } ... }
当选择具有此处理程序的菜单项时,将调用 EventHandler's
handle
方法。 该方法调用 doShowMessageDialog
方法,该方法显示消息对话框。
private void doShowMessageDialog(ActionEvent event) { var mi = (MenuItem) event.getSource(); String item = mi.getText(); var alert = new Alert(AlertType.INFORMATION); alert.setTitle("Information dialog"); alert.setHeaderText("Menu item selection information"); alert.setContentText(item + " menu item selected"); alert.showAndWait(); }
doShowMessageDialog
方法使用 Alert
控件创建一个信息对话框。 从事件源,我们确定菜单项的名称,该名称用于创建内容文本。

JavaFX ColorPicker
ColorPicker
是一个用于选择颜色值的内置对话框。 它允许用户从标准颜色调色板中选择颜色或定义自定义颜色。
package com.zetcode; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.ColorPicker; import javafx.scene.layout.HBox; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.stage.Stage; public class ColorPickerEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new HBox(25); root.setAlignment(Pos.BASELINE_CENTER); root.setPadding(new Insets(10)); var txt = new Text("ZetCode"); var font = Font.font(20); txt.setFont(font); var cp = new ColorPicker(); cp.setOnAction((ActionEvent event) -> txt.setFill(cp.getValue())); root.getChildren().addAll(cp, txt); var scene = new Scene(root, 300, 250); stage.setTitle("ColorPicker"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
在示例中,我们有一个 ColorPicker
和一个 Text
控件。 从颜色选择器中选择的颜色用于设置文本控件的前景色。
var txt = new Text("ZetCode"); var font = Font.font(20); txt.setFont(font);
创建一个 Text
控件。 我们放大其字体以获得更好的可见性。
var cp = new ColorPicker(); cp.setOnAction((ActionEvent event) -> txt.setFill(cp.getValue()));
创建一个 ColorPicker
并设置一个事件处理程序。 使用 ColorPicker
的 getValue
方法检索当前选择的颜色。 使用 setFill
方法更改文本控件的前景色。

JavaFX RadioButton
RadioButton
通常用于创建互斥的一系列项目。 当放置在 ToggleGroup
中时,只能选择一个 RadioButton
。 当选择 RadioButton
时,将发送 ActionEvent
。
package com.zetcode; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.RadioButton; import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class RadioButtonEx extends Application { private final double BORDER = 10d; private Label lbl2; @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new AnchorPane(); var vbox = new VBox(10); vbox.setPadding(new Insets(10)); var lbl1 = new Label("Difficulty"); lbl2 = new Label(""); lbl2.setStyle("-fx-background-color:wheat; -fx-padding: 0 0 0 5"); lbl2.prefWidthProperty().bind(stage.widthProperty().subtract(2 * BORDER)); var tg = new ToggleGroup(); tg.selectedToggleProperty().addListener(new MyToggleListener()); var rb1 = new RadioButton("Easy"); rb1.setToggleGroup(tg); rb1.setSelected(true); var rb2 = new RadioButton("Medium"); rb2.setToggleGroup(tg); var rb3 = new RadioButton("Hard"); rb3.setToggleGroup(tg); vbox.getChildren().addAll(lbl1, rb1, rb2, rb3); root.getChildren().addAll(vbox, lbl2); AnchorPane.setTopAnchor(vbox, BORDER); AnchorPane.setBottomAnchor(lbl2, BORDER); AnchorPane.setLeftAnchor(lbl2, BORDER); var scene = new Scene(root, 300, 250); stage.setTitle("RadioButton"); stage.setScene(scene); stage.show(); } private class MyToggleListener implements ChangeListener<Toggle> { @Override public void changed(ObservableValue<? extends Toggle> observable, Toggle oldValue, Toggle newValue) { var rb = (RadioButton) newValue; String txt = rb.getText(); lbl2.setText(txt); } } public static void main(String[] args) { launch(args); } }
该示例有三个单选按钮。 通过将它们放在一个切换组中,一次只能选择其中一个。
var lbl1 = new Label("Difficulty");
此标签提供对单选按钮的描述。
lbl2 = new Label(""); lbl2.setStyle("-fx-background-color:wheat; -fx-padding: 0 0 0 5"); lbl2.prefWidthProperty().bind(stage.widthProperty().subtract(2*BORDER));
此标签显示当前选定单选按钮的文本标签。 它的样式使用 setStyle
方法进行自定义。 放大标签以占据舞台的宽度减去指定边框。
var tg = new ToggleGroup(); tg.selectedToggleProperty().addListener(new MyToggleListener());
创建一个 ToggleGroup
并将侦听器添加到其 selectedToggleProperty
。
var rb1 = new RadioButton("Easy");
创建一个 RadioButton
控件。
rb1.setToggleGroup(tg);
setToggleGroup
方法将单选按钮设置为切换组。
rb1.setSelected(true);
setSelected
选中单选按钮。
private class MyToggleListener implements ChangeListener<Toggle> { @Override public void changed(ObservableValue<? extends Toggle> observable, Toggle oldValue, Toggle newValue) { var rb = (RadioButton) newValue; String txt = rb.getText(); lbl2.setText(txt); } }
在侦听器对象中,我们使用 getText
方法获取单选按钮的文本标签,并使用 setText
方法将其设置为标签。

JavaFX TabPane
TabPane
是一个控件,允许在一组 Tabs
之间切换。 一次只能看到一个选项卡。 TabPane
中的选项卡可以放置在窗口的四个侧面的任何一侧。 默认侧是顶部侧。
package com.zetcode; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.shape.Line; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class TabPaneEx extends Application { @Override public void start(Stage stage) { initUI(stage); } private void initUI(Stage stage) { var root = new StackPane(); var tabPane = new TabPane(); var tab1 = new Tab(); tab1.setText("Rectangle"); tab1.setContent(new Rectangle(100, 100, Color.LIGHTSTEELBLUE)); var tab2 = new Tab(); tab2.setText("Line"); tab2.setContent(new Line(0, 0, 100, 100)); var tab3 = new Tab(); tab3.setText("Circle"); tab3.setContent(new Circle(0, 0, 50)); tabPane.getSelectionModel().select(1); tabPane.getTabs().addAll(tab1, tab2, tab3); root.getChildren().add(tabPane); var scene = new Scene(root, 300, 250); stage.setTitle("TabPane"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
该示例包含一个 TabPane
控件,其中包含三个选项卡。 每个选项卡包含一个几何形状。 应用程序启动时将选择第二个选项卡。
var tabPane = new TabPane();
创建一个 TabPane
控件。
var tab1 = new Tab(); tab1.setText("Rectangle"); tab1.setContent(new Rectangle(100, 100, Color.LIGHTSTEELBLUE));
创建一个 Tab
。 其文本标签使用 setText
方法设置。 内容使用 setContent
方法设置。
tabPane.getSelectionModel().select(1);
TabPane
的选择模型处理选项卡的选择。 模型的 select
方法选择第二个选项卡。
tabPane.getTabs().addAll(tab1, tab2, tab3);
选项卡被插入到选项卡窗格中。 使用 getTabs
方法检索选项卡的内部列表。

在本章中,我们继续介绍了基本的 JavaFX 控件。