HOWTO · Java

JavaFX 主题

本教程演示如何使用 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 java.io.IOException;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;

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

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

输出:

菜单

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