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);
    }
}

输出:

JavaFX 主题

另一个来自 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 章中找到的另一个类。

输出:

JavaFX 主题

现在,让我们尝试操作 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);
    }
}

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

输出:

JavaFX 主题

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