CSS(层叠样式表,Cascading Style Sheets)原来是被用来在网页开发中表现HTML元素样式的一种文本标记语言。HTML用来展现内容,CSS被用来设计内容的样式,这样做的好处就是内容和样式相分离。CSS先后被用到Adobe的RIA开发技术Flex,C++的GUI框架Qt以及JavaFX技术上。如果对CSS不是很熟悉,没关系,十分钟入门CSS的一个教程:W3CSchool CSS教程。
JavaFX的CSS样式基于W3C CSS的2.1版本,是CSS 2.1的一个子集,不包含CSS 2.1的所有特性。同时JavaFX对该版本的CSS有所扩展。参考文档:JavaFX CSS Reference Guide。
JavaFX CSS有三种选择器:
1. type selector
每个JavaFX控件类都对应这一个CSS Type,我们可以使用类型选择器,控制该类型控件的外观。其对应的命名为:将JavaFX的类名成首字母小写,如果是由多个单词拼接的类名,将每个单词原来大写的首字母小写然后用连字符将多个单词连接。比如:
JavaFX Class | CSS type class |
---|---|
Button | button |
Label | label |
CheckBox | check-box |
TextField | text-field |
… | … |
类型选择器的用法如下:
.button {
-fx-background-color: blue;
}
这样我们就设置了所有Button的背景色为蓝色。其实类型选择器我们可以看做一种特殊的类选择器。
CSS中属性的命名规则是:以-fx开头,然后连接该类的属性,属性名称的单词首字母小写,然后用连字符连接拼接的属性单词。比如上面的-fx-background-color对应着Button的backgroundColor属性。具体的CSS属性我们可以参考JavaFX CSS Reference Guide文档。
2. class selector
类选择器和W3C的CSS中类选择器是一样的。比如下面的用法:
.font-large {
-fx-font-size: 16pt;
}
我们定义了一个font–large的类选择器。对于Node的任意子类都有一个getStyleClass()的方法,我们可以通过getStyleClass().add(“font-large”);将给类样式添加到指定的控件上。一个类选择器样式可以应用到多个控件上。
3. id selector
一个典型的ID选择器如下:
#lbl-title {
-fx-font-color: red;
-fx-font-size: 20px;
-fx-font-weight: bolder;
}
ID选择器由#开始进行定义。一般情况下一个ID选择器对应这唯一的一个控件。比如我们有一个ID为libTitle的Label,那么通过该CSS这个Label的字体会进行相应的改变。
Label lblTitle = new Label("欢迎来到中国");
lalTitle.setId("lbl-title");
最后说的是伪类选择器:
伪类的语法为:selector : pseudo-class {property: value}
比如我们设置当鼠标移动到Button上去时背景色变为绿色:
.button:hover {
-fx-background-color: green;
}
JavaFX中Node类定义的伪类有:
CSS Pseudo-class | Comments |
---|---|
disabled | applies when the disabled variable is true |
focused | applies when the focused variable is true |
hover | applies when the hover variable is true |
pressed | applies when the pressed variable is true |
show-mnemonic | apples when the mnemonic affordance (typically an underscore) should be shown. |
对于JavaFX中伪类元素我们可以查阅Oracle 的在线文档进行浏览和查询。
下面我们使用CSS美化一下我们在《JavaFX入门(三):使用Eclipse开发JavaFX程序 》一节中使用SceneBuilder拖拽出来的界面。
Eclipse中新建Java工程如下:
MainApplication.java文件是我们的主类文件,MainWindow.fxml是我们的FXML界面布局文件,MainStyle.css是我们的CSS样式文档。
我们的主界面使用GridPane,一个4×3的格网。第一行第一列是ImageVeiw用于显示Logo图标,第二列是Label用于显示标题;第二行第一列是一个Label(用户名),第二行第二列和第三列是一个TextFiled用于输入用户名;第三行第一列是一个Label(密码),第三行第二列和第三列是一个PasswordFiled用于输入密码。第四行第二列和第三列是一个AnchorPane,AnchorPane中是两个Button,一个锚定到左边,一个锚定到右边。在SceneBuilder中的设计图如下:
MainWindow.fxml代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.image.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.GridPane?>
<GridPane prefHeight="320.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="129.0" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="225.0" minWidth="10.0" prefWidth="220.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="99.0" minWidth="10.0" prefWidth="80.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 minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label fx:id="lblTitle" text="欢迎使用物联网系统" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
<Label text="用户名:" GridPane.halignment="RIGHT" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
<TextField GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="20.0" right="50.0" />
</GridPane.margin>
</TextField>
<Label text="密 码:" GridPane.halignment="RIGHT" GridPane.rowIndex="2" GridPane.valignment="CENTER" />
<PasswordField GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="2">
<GridPane.margin>
<Insets left="20.0" right="50.0" />
</GridPane.margin>
</PasswordField>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="3">
<children>
<Button layoutX="14.0" layoutY="17.0" mnemonicParsing="false" text="取消" AnchorPane.leftAnchor="20.0" />
<Button layoutX="197.0" layoutY="17.0" mnemonicParsing="false" text="登录" AnchorPane.rightAnchor="50.0" />
</children>
</AnchorPane>
<ImageView fitHeight="60.0" fitWidth="60.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@images/earth.png" />
</image>
<GridPane.margin>
<Insets left="20.0" />
</GridPane.margin>
</ImageView>
</children>
</GridPane>
运行图如下:
我们的主函数MainApplication.java代码如下:
package cn.tzy.fx.application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class MainApplication extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
try {
GridPane root = (GridPane) FXMLLoader.load(getClass().getResource("MainWindow.fxml"));
Scene scene = new Scene(root, 400, 320);
primaryStage.setScene(scene);
primaryStage.setTitle("Hello World");
primaryStage.setResizable(false);
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("images/earth.png")));
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
下面我们利用CSS调整界面样式:
/*root类选择器给所有的元素设置样式*/
.root {
-fx-font-family: "微软雅黑";
-fx-font-size: 16px;
-fx-background-image: url(images/background.png);
-fx-background-size: stretch stretch;
-fx-background-position: center center;
}
/*button类型选择器设置所有Button的背景色*/
.button {
-fx-background-color: darkturquoise;
}
/*hover伪类选择器设置鼠标移过Button时的背景色*/
.button:hover {
-fx-background-color: lightskyblue;
}
/*id选择器设置Label标题的样式*/
#lblTitle {
-fx-font-size: 20px;
-fx-font-weight: bolder;
-fx-text-fill: darkslategray;
}
如何将我们的CSS样式文件添加上去呢?
1. 在主程序的start()方法中添加一句代码:scene.getStylesheets().add(
getClass().getResource("MainStyle.css")
.toExternalForm());
2. 在我们的FXML文件中给根布局控件GridPane添加属性stylesheets="@MainStyle.css"
即可,注意是@后面跟我们的CSS文件路径全名称。
看看最终运行效果吧!