如何在JavaFX应用程序中添加外部CSS文件

1,027 阅读11分钟

在JavaFX应用程序中添加外部CSS文件

你是否在为JavaFX应用程序添加外部CSS文件或将外部设计的样式表链接到你的程序中时遇到困难?在这篇文章中,我们将探讨如何解决这些问题。

当人们决定对JavaFX应用程序进行样式设计时,挑战就来了。这是一个繁琐的程序,因为每个元素都需要它的样式。设计师要记住以前在不同元素上使用的样式,这个问题一再出现。

在FXML文件中,也很难跟上代码中的样式,因为它不是连续的。你可能也注意到,在造型过程中使用的关键词与HTML文件的关键词不同。

主要收获

在文章的最后,读者应该知道。

  • 使用变量保存一个重复的样式以方便在其他元素上使用。
  • 在应用程序中添加一个外部样式表。
  • 通过添加JavaFX类来引用样式表中的元素。
  • 将样式表链接到许多场景中。

前提条件

要学习这篇文章,你将需要。

  • 在你的机器上安装Java开发工具包。建议使用市场上最新的JDK。本文使用的是JDK 17。
  • 一个好的Java IDE。建议使用最新版本的IntelliJ终极版。因为它有对JavaFX的支持。本文使用了IntelliJ版本2021.2.2
  • 一个良好的互联网连接。这是用来获取快速开发的索引的。它也将在项目的生成中使用。

先决条件可以随着时间的变化而改变,从文章发表的那一天开始。请确保跟进所述技术的最新版本。所用的应用程序的外观也可能根据发布日期的不同而变化。

塑造JavaFX应用程序风格的方法

一个JavaFX应用程序可以使用不同的风格进行定制。这些风格包括以下几种。

  • 使用内部样式。这是由SceneBuilder默认提供的。
  • 使用预先保存的变量。这些变量可以被重复使用,从而减少FXML文件中的代码重复。
  • 使用外部CSS文件。这个文件可以根据项目的要求进行定制。它减少了代码的重复和错误。

在这篇文章中,上述所有内容将在一个JavaFX应用程序中演示。要做到这一点,我们将遵循以下步骤。

  • 设计一个JavaFX登录应用程序的样本。
  • 使用正常的内部样式为JavaFX应用程序设计样式。
  • 使用预先保存的样式变量为应用程序添加样式。
  • 使用一个外部CSS文件来应用样式。

创建一个新的JavaFX文件

  • 到IDE去。打开它,点击创建新项目按钮。在下面的图片中查看一下。

new Javafx application

  • 选择BootstrapFXControlsFXFormsFX作为项目的依赖项。这些都显示在下面的图片中。

App dependencies

文件夹结构

应用程序的文件夹结构如下图所示。

.
├── src
│   └── main
│       ├── java
│          └── com.login
│            ├── javafxstyle
│                  ├── HelloApplication.java
│                  └── HelloController.java
|            └── module-info.java
│       └── resources
│          └── com.login.javafxstyle
│               └── hello-view.fxml
├── target
├── javafx-style.iml
└── pom.xml

在FXML应用程序内添加代码

在上述文件夹结构中显示的HelloController.java 文件内删除以下代码。

@FXML
private Label welcomeText;

@FXML
protected void onHelloButtonClick() {
    welcomeText.setText("Welcome to JavaFX Application!");
}

这将删除应用程序中 "Hello按钮 "的功能。

使用SceneBuilder删除包含Hello buttonhello-view.fxml 文件中的Label的V-Box ,如下图所示。

Delete the VBox

如果没有安装SceneBuilder,请在这里查看如何在IntelliJ中安装和配置它。

这篇文章还展示了如何在IntelliJ终极版上设置JavaFX。如果出现任何错误,请确保重新启动IDE。

上面的步骤删除了文件中的这段代码。


<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"
      fx:controller="com.example.demo.HelloController">
  <padding>
    <Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
  </padding>

  <Label fx:id="welcomeText"/>
  <Button text="Hello!" onAction="#onHelloButtonClick"/>
</VBox>

下载login.png 图像。将图像复制粘贴到hello-view.fxml 文件所在的位置。复制下面的代码,并将其粘贴到被删除的代码所在的hello-view.fxml 文件中。


<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
            prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.2"
            xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="com.login.javafxstyle.HelloController">
  <children>
    <Label fx:id="loginTitleLabel" layoutX="430.0" layoutY="35.0" text="Login"/>
    <ImageView fitHeight="400.0" fitWidth="325.0" pickOnBounds="true" preserveRatio="true">
      <image>
        <Image url="@login.png"/>
      </image>
    </ImageView>
    <Label fx:id="enterDetailsLabel" layoutX="330.0" layoutY="120.0" text="Enter the login details below:"/>
    <Label fx:id="usernameLabel" layoutX="333.0" layoutY="160.0" text="Username:"/>
    <TextField fx:id="usernameTextField" layoutX="415.0" layoutY="157.0" promptText="john.doe@email.com"/>
    <Label fx:id="passwordLabel" layoutX="333.0" layoutY="198.0" text="Password:"/>
    <PasswordField fx:id="passwordPasswordField" layoutX="415.0" layoutY="195.0" promptText="********"/>
    <CheckBox fx:id="rememberMeCheckBox" layoutX="375.0" layoutY="245.0" mnemonicParsing="false"
              text="Remember me?"/>
    <Label fx:id="errorLabel" layoutX="387.0" layoutY="280.0" prefHeight="16.0" prefWidth="171.0"
           text="Sign in error!"/>
    <Button fx:id="cancelButton" layoutX="370.0" layoutY="310.0" mnemonicParsing="false" text="Cancel"/>
    <Button fx:id="signInButton" layoutX="490.0" layoutY="310.0" mnemonicParsing="false" text="Sign in"/>
    <Button fx:id="forgotPasswordButton" layoutX="400.0" layoutY="350.0" mnemonicParsing="false"
            text="Forgot password?"/>
  </children>
</AnchorPane>

当使用SceneBuilder查看时,该步骤产生以下输出。

Login page output

前往HelloApplication.java 文件,并确保将场景尺寸设置为600 x 400。

Scene scene=new Scene(fxmlLoader.load(),600,400);

给应用程序添加样式

如前所述,有三种方法可以定制应用程序的外观。

1.添加内部造型

它可以通过两种方式实现。

  • 通过把它硬编码到应用程序中。
  • 通过使用SceneBuilder。
硬编码

打开FXML文件。点击左下角靠近状态栏的Text 选项,以文本格式查看窗口。在文件中,在fx:id为loginTitleLabel的标签下,添加以下样式。


<Label fx:id="loginTitleLabel" layoutX="430.0" layoutY="35.0"
       style="-fx-font-size: 40; -fx-text-fill: linear-gradient(from 0% 0% to 100% 200%, repeat, aqua 0%, red 50%); -fx-font-weight: BOLD;"
       text="Login" textFill="#31ebfc"/>

这个样式使它变得巨大粗体,并在其中填充一些线性梯度

fx:identerDetailsLabel 的标签中,添加以下样式。


<Label fx:id="enterDetailsLabel" layoutX="330.0" layoutY="120.0"
       style="-fx-text-fill: #727272; -fx-font-size: 15; -fx-font-weight: BOLD;"
       text="Enter the login details below:"/>

fx:idusernameLabelpasswordLabel 的标签中,分别添加以下内容。


<Label fx:id="usernameLabel" layoutX="333.0" layoutY="160.0"
       style="-fx-text-fill: #727272; -fx-font-size: 15;"
       text="Username:"/>


<Label fx:id="passwordLabel" layoutX="333.0" layoutY="198.0"
       style="-fx-text-fill: #727272; -fx-font-size: 15;"
       text="Password:"/>
  • 给复选框添加以下样式。

<CheckBox fx:id="rememberMeCheckBox" layoutX="375.0" layoutY="245.0" mnemonicParsing="false"
          style="-fx-text-fill: #727272;" text="Remember me?"/>

fx:iderrorLabel 的标签上添加以下样式。


<Label fx:id="errorLabel" layoutX="387.0" layoutY="280.0" prefHeight="16.0" prefWidth="171.0"
       style="-fx-text-fill: red;" text="Sign in error!"/>

至于其余的按钮,下面将是它们的样式。


<Button fx:id="cancelButton" layoutX="370.0" layoutY="310.0" mnemonicParsing="false"
        onAction="#onCancelButtonClick"
        style="-fx-background-color: #4385F4; -fx-text-fill: white; -fx-font-size: 13;" text="Cancel"/>
<Button fx:id="signInButton" layoutX="490.0" layoutY="310.0" mnemonicParsing="false"
        onAction="#onSignInButtonClick"
        style="-fx-background-color: #4385F4; -fx-text-fill: white; -fx-font-size: 13;" text="Sign in"/>
<Button fx:id="forgotPasswordButton" layoutX="400.0" layoutY="350.0" mnemonicParsing="false"
        style="-fx-background-color: transparent; -fx-text-fill: #727272;" text="Forgot password?"
        underline="true"/>

onAction 属性将按钮链接到控制器中的一个函数。在一个触发事件中,比如点击按钮,该函数会被执行。

打开HelloController 类,粘贴下面的代码。请确保添加所需的导入。

/*Import JavaFX controls*/
@FXML
Button cancelButton, signInButton;

@FXML
Label errorLabel, loginTitleLabel;

@FXML
TextField usernameTextField;

@FXML
PasswordField passwordPasswordField;

/*Close the scene once the cancel button is clicked*/
@FXML
protected void onCancelButtonClick() {
    Stage stage = (Stage) cancelButton.getScene().getWindow();
    stage.close();
}

/* Make the label with the fx:id of 'errorLabel' change its text and color on Sign in Button click */
@FXML
protected void onSignInButtonClick() {
    errorLabel.setText("Sign In Success!");
    errorLabel.setStyle("-fx-text-fill: GREEN;");
}

通过HelloApplication.java 文件运行该应用程序,如下图所示。

Run the application

输出看起来如下图所示。

Final output

正如我们所看到的,该应用程序如期运行。

使用SceneBuilder

使用SceneBuilder选项打开FXML文件,该选项位于窗口左下方靠近状态栏的位置。

要为应用程序中使用的控件添加样式,请点击所需的控件。在本例中,从fx:id 的标签开始,loginTitleLabel

在右侧的标签上,在属性部分下,注意SceneBuilder会自动识别设置在该元素上的可用格式。

勾选下划线的复选框。在样式部分,通过点击+ 符号添加以下属性。

  • -fx-background-color:#f3f3f3
  • -fx-border-radius:5
  • -fx-border-color:linear-gradient(from 0% 0% to 100% 200%, repeat, aqua 0%, red 50%)

属性选项卡中的SceneBuilder造型部分将看起来如下。

loginTitle SceneBuilder styling

点击Remember me 复选框,选择Selected 选项。运行该应用程序。

它产生的输出如下。

Second Output

正如所见,SceneBuilder在属性布局代码标签中提供了更多的选项。使用这种方法添加造型非常简单,因为有GUI的支持。

2.使用预先保存的变量

要做到这一点,造型将被存储在变量中。这些变量将是可重复使用的代码片段。它们可以减少代码错误,特别是当造型较长且难以记忆的时候。

打开应用程序中的控制器。在控件的导入上面,添加变量,为应用程序保存样式。

String successStyle = String.format("-fx-border-color: #4fd800; -fx-border-width: 2; -fx-border-radius: 5;");
String successStyleGradient = String.format("-fx-text-fill: #4fd800;");

现在,使用这些变量为页面的不同组件设置样式。一个例子是TextField和PasswordField。

将下面的代码粘贴在其他函数下面的onSignInButtonClick

usernameTextField.setStyle(successStyle);
passwordPasswordField.setStyle(successStyle);
signInButton.setStyle(successStyleGradient);

运行该应用程序。当点击Sign-In button ,输出结果如下所示。

Third output

从上面的步骤可以看出,造型可以在项目中快速重复使用,以获得高效的代码。它使开发人员的开发变得容易,特别是在有许多不同元素的预设样式的大型项目中。

3.使用外部CSS文件

当涉及到高级造型时,最好使用这种造型。它不仅易于管理,而且还支持代码的可读性。

有两种方法可以将外部样式表添加到程序中。这两种方法是:

  • 通过HelloApplication.java 文件来添加它。
  • 通过SceneBuilder或硬编码来添加它。

让我们快速看一下这两种方法。

1.通过主类文件添加

要添加它,在FXML文件的位置创建一个新的CSS文件。在HelloApplication.java 文件中,添加下面这行代码。

scene.getStylesheets().add(getClass().getResource("styles.css").toExternalForm());

这将把styles.css 文件中的样式应用到创建的场景中。

2.通过SceneBuilder或硬编码来添加它

SceneBuilder将一个特定的样式表样式添加到应用程序中的一个特定控件上。这种添加方式与上面提到的使用场景风格化的方式不同,后者是将风格化添加到整个场景中。

因此,人们需要反复地重复这些步骤。

  1. 在SceneBuilder视图中,点击首先添加的AnchorPane。
  2. 在属性标签中,在 "JavaFX CSS "部分,点击 "Stylesheets "选项。
  3. 选择CSS文件,就可以了。

人们也可以通过链接它们来应用某个特定类的样式来控制应用程序。

这种链接可以通过在SceneBuilder中 "JavaFX CSS "部分的 "Styles Class "选项中向控件添加CSS类来实现。该类可以与应用程序已知的类不同。它可以被定义在添加到控件或场景的样式表中。这将在本文后面的代码中显示。

当AnchorPane的CSS类被设置为 "唯一 "时,它产生的代码如下所示,在文本视图中可以看到。

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0"
            styleClass="unique" xmlns="http://javafx.com/javafx/11.0.2" xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="com.login.javafxstyle.HelloController">

在添加任何样式之前,首先让我们看看样式格式是什么样子的。

外部样式设置格式

对于外部CSS样式,如果想引用组件的名称(fx:id),他们会在样式前使用一个# 符号。该格式如下所示。

#titleLabel {
  /* Styling for the Control with the fx:id of titleLabel */
}

提供的控件,被CSS文件以类的形式引用。因此,要引用一个完整的类的集合,请以. (句号)符号开始。随后在样式前用小字写上控件的名称。

这类控件及其类名的例子有。

  • Button: 按钮
  • CheckBox:复选框
  • Label: 标签
  • RadioButton:放射状按钮
  • TextField: 文本字段
  • TextArea: 文本区(textarea

CSS格式的样本如下所示。

.root {
  /*This applies styling for the root node*/
}

.label {
  /* Styling for all Control with the class of 'label' */
}

对于JavaFX应用程序的任何样式,从-fx- 文本开始,然后是控件或JavaFX项目所支持的样式

并非所有控件都支持所有的样式。在应用之前,一定要找出可以应用于每个控件的样式,以及它的作用。

现在,在创建的StyleSheet中,将下面的代码粘贴到其中。

.root {
  /*This applies styling for the root node*/
  -fx-background-color: linear-gradient(
    from 0% 0% to 100% 200%,
    repeat,
    #fbeee6 0%,
    #cde0c9 50%
  );
  -fx-font-family: "Lucida Console";
}

.label {
  /* Styling for all Control with the class of 'label' */
  -fx-padding: -2px;
  -fx-start-margin: 2px;
  -fx-end-margin: 2px;
}

.guide-link {
  /*Unique class customized by user*/
}

#loginTitleLabel,
#errorLabel {
  -fx-font-family: "Chilanka";
}

它为所有的根内容、标签控件以及loginTitleLabel和errorLabel控件都应用了样式设计。

此外,还可以应用更多的样式。这些包括复选框检查的后效。要实现下面的效果,请复制并粘贴下面的代码到其中。

/* Checkbox formatting */
.check-box .mark {
  -fx-shape: "M2,0L5,4L8,0L10,0L10,2L6,5L10,8L10,10L8,10L5,6L2,10L0,10L0,8L4,5L0,2L0,0Z";
}

.check-box:selected .mark {
  -fx-background-color: #0181e2ff;
}

/*Once the button is clicked, it will display the following effect when one hovers over it*/
.button:hover {
  -fx-background-color: linear-gradient(#2a5058, #61a2b1);
}

这就产生了下面的输出。

External CSS

多个场景实例的外部CSS

添加一行代码,首先指向样式表的位置,然后根据创建的许多场景来引用它。

打开HelloApplication.java 文件,粘贴下面的代码。

/*Multiple scenes created*/
Scene scene = new Scene(fxmlLoader.load(), 600, 400);
Scene scene1 = new Scene(fxmlLoader.load(), 800, 400);
Scene scene2 = new Scene(fxmlLoader.load(), 1000, 400);
Scene scene3 = new Scene(fxmlLoader.load(), 1200, 400);
Scene scene4 = new Scene(fxmlLoader.load(), 1200, 600);
Scene scene5 = new Scene(fxmlLoader.load(), 1200, 1000);

/*Show the location of the CSS resource file*/
String css = this.getClass().getResource("styles.css").toExternalForm();

/*Add the stylesheet quickly to the many scenes*/
scene.getStylesheets().add(css);
scene1.getStylesheets().add(css);
scene2.getStylesheets().add(css);
scene3.getStylesheets().add(css);
scene4.getStylesheets().add(css);
scene5.getStylesheets().add(css);

结论

总之,对最终用户来说,应用程序的外观和功能一样重要。它越有吸引力,用户就越能接受它。先进的造型设计有助于创造现代的UI设计。随着世界的发展,设计师必须不断关注市场上的改进和新的UI设计。

JavaFX是一个对任何Java程序都非常兼容的UI框架。它既可以用于简单的项目,也可以用于涉及复杂设计的高级项目。了解JavaFX程序中的设计和造型是非常重要的。它允许人们在为桌面应用程序构建现代设计时超越想象。

我们已经经历了在你的JavaFX程序中添加样式。来吧,在你的应用程序中尝试不同的风格。