JavaFX 主题

Sheeraz Gul 2022年4月26日
JavaFX 主题

JavaFX 用于 GUI 设计。那里有许多可用的主题,我们可以在这些主题上设计和构建我们的应用程序。

本教程将列出一些著名的 JavaFX 主题,并演示如何使用和操作它们来设计我们的应用程序。

JavaFX 主题列表

  • AeroFX:来自 GUIGARAGE 的 JavaFX 主题,它复制了 Windows 7 应用程序的外观,请在此处进行检查。
  • AquaFX:来自 GUIGARAGE 的 JavaFX 主题,它复制 Mac OS 应用程序的外观,请查看此处
  • Flatter:来自 GUIGARAGE 的平面设计 GUI 主题,请在此处查看。
  • JMetro:受 Microsoft fluent 设计系统启发的 JavaFX 主题,请查看此处
  • jbootfx:使用 Bootstrap 进行响应式设计的 JavaFX 主题,请在此处查看。
  • MaterialFX:用于 Google Material Design 外观的 JavaFX 主题,请查看此处
  • Flat Red:一个简单的平面和红色 JavaFX 主题,请查看这里

上面的大多数主题都需要 maven 支持才能将它们作为项目加载。让我们使用简单的 Flat Red 主题并尝试操作它。

Flat Red,一个简单的 Flat 和 Red JavaFX 主题

Flat Red 是 GitHub 上提供的一个简单的 JavaFX 主题,提供不同的设计,可以根据我们的需要进行操作。让我们先尝试一些原件。

Flat Red 主题第 15 章中的 StyleButtons 将生成电话拨号视图。

例子:

package jfx9be;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;

public class StyleButtons extends Application {

    @Override
    public void start(Stage primaryStage) {

        BorderPane root = new BorderPane();
        Scene scene = new Scene(root, 180, 250);
        scene.getStylesheets()
             .add(getClass().getResource("mobile_buttons.css")
                            .toExternalForm());
        String[] keys = {"1", "2", "3",
                         "4", "5", "6",
                         "7", "8", "9",
                         "*", "0", "#"};
        GridPane numPad = new GridPane();
        numPad.getStyleClass().add("num-pad");

        for (int i=0; i < 12; i++) {
            Button button = new Button(keys[i]);
            button.getStyleClass().add("num-button");
            numPad.add(button, i % 3, (int) Math.ceil(i/3) );
        }
        // Call button
        Button call = new Button("Call");
        call.setId("call-button");
        call.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        numPad.add(call, 0, 4);
        GridPane.setColumnSpan(call, 3);

        GridPane.setHgrow(call, Priority.ALWAYS);
        root.setCenter(numPad);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

输出:

电话

另一个来自 Flat Red 主题第 15 章的示例生成了一个交互式真假开关。

例子:

package jfx9controls.csspseudoclass;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Demo extends Application {
    private MyCtrl       myCtrl;
    private ToggleButton buttonInteractive;

    @Override public void init() {
        myCtrl            = new MyCtrl();
        buttonInteractive = new ToggleButton("Interactive: false");
        registerListeners();
    }

    private void registerListeners() {
        buttonInteractive.setOnAction(actionEvent -> {
            myCtrl.setInteractive(!myCtrl.isInteractive());
            buttonInteractive.setText("Interactive: " + (myCtrl.isInteractive() ? "true" : "false"));
        });
    }

    @Override public void start(Stage stage) throws Exception {
        VBox pane = new VBox();
        pane.setPadding(new Insets(10, 10, 10, 10));
        pane.setAlignment(Pos.CENTER);
        pane.setSpacing(10);
        pane.getChildren().addAll(myCtrl, buttonInteractive);
        VBox.setMargin(myCtrl, new Insets(10, 10, 10, 10));

        Scene scene = new Scene(pane);

        stage.setTitle("CSS PseudoClass");
        stage.setScene(scene);
        stage.show();
    }

    @Override public void stop() {}

    public static void main(final String[] args) {
        Application.launch(args);
    }
}

此示例包括在 Flat Red 的第 15 章中找到的另一个类。

输出:

转变

现在,让我们尝试操作 Flat Red Theme 中的一个示例;我们从第 15 章中选择 LookNFeelChooser。

例子:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="427.0" prefWidth="596.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children> <Accordion layoutX="102.0" layoutY="129.5" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns:fx="http://javafx.com/fxml">
    <panes>
        <TitledPane animated="false" text="Theme Demo Buttons">
            <content>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children> <GridPane layoutX="38.5" layoutY="82.5" prefHeight="259.0" prefWidth="421.0" xmlns:fx="http://javafx.com/fxml">
    <columnConstraints>
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
    </columnConstraints>
    <rowConstraints>
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    </rowConstraints>
<children> <RadioButton mnemonicParsing="false" selected="true" text="Radio_Button" GridPane.columnIndex="0" GridPane.rowIndex="1" /><Button mnemonicParsing="false" text="Demo Button" GridPane.columnIndex="0" GridPane.rowIndex="0" /><ToggleButton mnemonicParsing="false" text="Toggle_Button" GridPane.columnIndex="1" /><CheckBox layoutX="147.7890625" layoutY="74.5" mnemonicParsing="false" selected="true" text="CheckBox" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</children>
</GridPane>
</children> </AnchorPane>
            </content>
        </TitledPane>
        <TitledPane animated="false" text="Progress Controls">
            <content>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children> <ProgressBar layoutX="88.0" layoutY="55.0" prefWidth="200.0" progress="0.98" /><ProgressIndicator layoutX="168.5" layoutY="99.0" progress="0.98" />
</children> </AnchorPane>
            </content>
        </TitledPane> <TitledPane animated="false" text="Scroll Bars &amp; Sliders" xmlns:fx="http://javafx.com/fxml">
    <content>
        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children> <ScrollBar layoutX="94.0" layoutY="31.0" prefHeight="14.0" prefWidth="312.0" /><ScrollBar layoutX="33.0" layoutY="29.0" orientation="VERTICAL" prefHeight="210.0" prefWidth="14.0" /><Slider layoutX="94.0" layoutY="145.0" prefHeight="14.0" prefWidth="310.0" /><Slider layoutX="463.0" layoutY="36.0" orientation="VERTICAL" prefHeight="206.0" prefWidth="14.0" />
</children> </AnchorPane>
    </content>
</TitledPane>
    </panes>
</Accordion>
</children> </AnchorPane>

上面的代码是第 15 章的 fxml,我们根据需要进行了编辑。

这个 fxml 的 Java 代码是:

package application;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.control.Menu;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.io.IOException;


public class Java_FX_Example extends Application {

    @Override public void init() {
        Font.loadFont(LookNFeelChooser.class.getResourceAsStream("Roboto-Thin.ttf"), 10).getName();
        Font.loadFont(LookNFeelChooser.class.getResourceAsStream("Roboto-Light.ttf"), 10).getName();
    }

    @Override public void start(Stage primaryStage) throws IOException {
        BorderPane root_border_pane    = new BorderPane();
        Parent     Parent_content = FXMLLoader.load(getClass().getResource("lnf_demo.fxml"));
        Scene      Demo_scene   = new Scene(root_border_pane, 650, 550, Color.WHITE);
        root_border_pane.setCenter(Parent_content);

        // Theme Menu bar
        MenuBar Demo_menu_Bar = new MenuBar();

        // Theme  file menu
        Menu     Demo_file_Menu = new Menu("_File");
        MenuItem Menu_exit_Item = new MenuItem("Close");
        Menu_exit_Item.setAccelerator(new KeyCodeCombination(KeyCode.X, KeyCombination.SHORTCUT_DOWN));
        Menu_exit_Item.setOnAction(ae -> Platform.exit());

        Demo_file_Menu.getItems().add(Menu_exit_Item);
        Demo_menu_Bar.getMenus().add(Demo_file_Menu);

        // Look and feel menu
        Menu JFXPBE_Menu = new Menu("_JFXBE_Example");
        JFXPBE_Menu.setMnemonicParsing(true);
        Demo_menu_Bar.getMenus().add(JFXPBE_Menu);
        root_border_pane.setTop(Demo_menu_Bar);

        // Look and feel selection
        MenuItem option1_Menu_Item = new MenuItem("Option 1");
        option1_Menu_Item.setOnAction(ae -> {
            Demo_scene.getStylesheets().clear();
            //setUserAgentStylesheet(null);
            setUserAgentStylesheet(STYLESHEET_CASPIAN);
        });
        MenuItem option2_Menu_Item = new MenuItem("Option 2");
        option2_Menu_Item.setOnAction(ae -> {
            Demo_scene.getStylesheets().clear();
            //setUserAgentStylesheet(null);
            setUserAgentStylesheet(STYLESHEET_MODENA);
        });
        MenuItem option3_Menu_Item = new MenuItem("Option 3");
        option3_Menu_Item.setOnAction(ae -> {
            Demo_scene.getStylesheets().clear();
            setUserAgentStylesheet(null);
            Demo_scene.getStylesheets()
                .add(getClass()
                .getResource("controlStyle1.css")
                .toExternalForm());
        });
        MenuItem option4_Menu_Item = new MenuItem("Option 4");
        option4_Menu_Item.setOnAction(ae -> {
            Demo_scene.getStylesheets().clear();
            setUserAgentStylesheet(null);
            Demo_scene.getStylesheets()
                .add(getClass()
                .getResource("controlStyle2.css")
                .toExternalForm());
        });

        MenuItem option5_Menu_Item = new MenuItem("Option 5");
        option5_Menu_Item.setOnAction(ae -> {
            Demo_scene.getStylesheets().clear();
            setUserAgentStylesheet(null);
            Demo_scene.getStylesheets()
                .add(getClass()
                .getResource("sky.css")
                .toExternalForm());
        });

        MenuItem option6_Menu_Item = new MenuItem("Option 6");
        option6_Menu_Item.setOnAction(ae -> {
            Demo_scene.getStylesheets().clear();
            setUserAgentStylesheet(null);
            Demo_scene.getStylesheets()
                .add(getClass()
                .getResource("flatred.css")
                .toExternalForm());
        });

        JFXPBE_Menu.getItems()
                    .addAll(option1_Menu_Item,
                            option2_Menu_Item,
                            option3_Menu_Item,
                            option4_Menu_Item,
                            option5_Menu_Item,
                            option6_Menu_Item);

        primaryStage.setTitle("JAVA_FX Themes Example");
        primaryStage.setScene(Demo_scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

上面的代码将生成一个框,该框将包含带有按钮、进度报告和其他选项的不同菜单。

输出:

菜单

我们可以根据我们的要求使用任何主题;这些主题不限于上述列表。还有其他几个选项,但这些是最常用的选项。

Author: Sheeraz Gul
Sheeraz Gul avatar Sheeraz Gul avatar

Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.

LinkedIn Facebook