ZetCode

JavaFX 基础控件 II

最后修改于 2023 年 10 月 18 日

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

JavaFX DatePicker

DatePicker 是一个用于选择日期的控件。

com/zetcode/DatePickerEx.java
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 方法设置为标签控件。

DatePicker
图:DatePicker

JavaFX MenuBar

MenuBarMenu 对象组成,这些对象包含 MenuItem 对象 - 应用程序的命令。它传统上放置在应用程序窗口的顶部。

com/zetcode/MenuBarEx.java
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 控件创建一个信息对话框。 从事件源,我们确定菜单项的名称,该名称用于创建内容文本。

MenuBar
图:MenuBar

JavaFX ColorPicker

ColorPicker 是一个用于选择颜色值的内置对话框。 它允许用户从标准颜色调色板中选择颜色或定义自定义颜色。

ColorPickerEx.java
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 并设置一个事件处理程序。 使用 ColorPickergetValue 方法检索当前选择的颜色。 使用 setFill 方法更改文本控件的前景色。

ColorPicker
图:ColorPicker

JavaFX RadioButton

RadioButton 通常用于创建互斥的一系列项目。 当放置在 ToggleGroup 中时,只能选择一个 RadioButton。 当选择 RadioButton 时,将发送 ActionEvent

com/zetcode/RadioButtonEx.java
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 方法将其设置为标签。

RadioButton
图:RadioButton

JavaFX TabPane

TabPane 是一个控件,允许在一组 Tabs 之间切换。 一次只能看到一个选项卡。 TabPane 中的选项卡可以放置在窗口的四个侧面的任何一侧。 默认侧是顶部侧。

com/zetcode/TabPaneEx.java
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 方法检索选项卡的内部列表。

TabPane
图:TabPane

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