移除JavaFX TitledPane的鼠标悬浮效果 Remove mouse hover effect on JavaFX TitledPane

有时候我会用JavaFX的TitledPane来区分UI中的不同部分,像这样。

TitledPane tp1 = new TitledPane();
tp1.setCollapsible(false);
TitledPane tp2 = new TitledPane();
tp2.setCollapsible(false);

通过setCollapsible()这个函数,让TitledPane不可折叠,然后用一个VBox把它们排好。

但是当我们把鼠标移动到TitledPane的标题栏上时,标题栏的背景颜色还是会变化,这就会给用户一种可以点击的错觉。经过一波操作之后,我发现可以通过修改TitledPane的css来解决这个问题。

tp1.setStyle("-fx-hover-base: -fx-base;");

解释:JavaFX默认使用的css文件叫做modena.css,存放在com.sun.javafx.scene.control.skin.modena包中,在这个css文件中关于TitledPane的部分为

/*******************************************************************************
 *                                                                             *
 * TitledPane                                                                  *
 *                                                                             *
 ******************************************************************************/

.titled-pane {
    -fx-text-fill: -fx-text-base-color;
}
.titled-pane:focused {
    -fx-color: -fx-base;
}
.titled-pane > .title {
    -fx-background-color:
        linear-gradient(to bottom,
            derive(-fx-color,-15%) 95%,
            derive(-fx-color,-25%) 100%
        ),
        -fx-inner-border, -fx-body-color;
    -fx-background-insets: 0, 1, 2;
    -fx-background-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0;
    -fx-padding: 0.3333em 0.75em 0.3333em 0.75em; /* 4 9 4 9 */
}
/* alternative focus using the ring around the entire title area */
/*.titled-pane:focused > .title {
    -fx-background-color: -fx-faint-focus-color, -fx-focus-color, -fx-inner-border, -fx-body-color;
    -fx-background-insets: 0, 0.7, 2, 3;
}*/
/* focus purely on the arrow */
.titled-pane:focused > .title > .arrow-button > .arrow {
    -fx-background-color: -fx-focus-color, -fx-mark-color;
    -fx-background-insets: -1, 0;
    -fx-effect: dropshadow(two-pass-box , -fx-focus-color, 5, 0.2 , 0, 0);
}
.titled-pane > .title > .arrow-button {
    -fx-background-color: null;
    -fx-background-insets: 0;
    -fx-background-radius: 0;
    -fx-padding: 0.0em 0.583em 0.0em 0.0em; /* 0 7 0 0 */
}
.titled-pane > .title > .arrow-button > .arrow {
    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
    -fx-background-insets: 1 0 -1 0, 0;
    -fx-padding: 0.25em 0.3125em 0.25em 0.3125em; /* 3 3.75 3 3.75 */
    -fx-shape: "M 0 0 h 7 l -3.5 4 z";
}
.titled-pane > .title:hover {
    -fx-color: -fx-hover-base;
}
/* alternative content using a border and a grad to transparent background - why should TitledPane content have a colour? */
.titled-pane > *.content {
    -fx-border-color: -fx-box-border;
    -fx-border-insets: -1 0 0 0;
    -fx-background-color: linear-gradient(from 0px 0px to 0px 5px, derive(-fx-background, -6%), -fx-background);
}

其中的高亮部分便是用来实现鼠标悬浮功能的。-fx-hover-base是一个在前文中定义好的颜色设置,内容如下

-fx-hover-base: ladder(
    -fx-base,
    derive(-fx-base,20%) 20%,
    derive(-fx-base,30%) 35%,
    derive(-fx-base,40%) 50%
 );

我没有继续深究-fx-base是什么样子,尝试了一下-fx-hover-base: -fx-base,奈斯,问题解决。

之前的代码有一个弊端,就是会让这个TitledPane中间的所有按钮也失去悬浮效果。为了解决这个问题,我又搞出了下面的代码。

Platform.runLater(() -> tp1.lookup(".title").setStyle("-fx-hover-base: -fx-base"));

Platform.runLater()是让参量中的lambda表达式在程序跑起来之后再在UI线程执行,lookup()函数会找到与参数中的css选择器对应的Node,在这个例子里就是标题栏所对应的HBox。然后我们对这个标题栏应用css,就不会影响TitledPane内部的东西了。当然如果你在标题栏放按钮还是会有问题,但是这种情况我暂时不考虑。

另一种解决方法就是在整个程序的css文件加上.titled-pane.static > .title:hover { -fx-color: -fx-base; }然后再用tp1.getStyleClass().add("static");给TitledPane标记为对应的css类。这样最直接。

JavaFX的很多问题都可以通过修改css来解决,之后可能会深入了解一下。

发表评论

您的电子邮箱地址不会被公开。