10

我正在使用 JavaFX SceneBuilder,但我将在下面粘贴 FXML,因为它很短。我有一个非常简单的窗口,在锚窗格内有一个拆分窗格。这是 FXML:

<?xml version="1.0" encoding="UTF-8"?>

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
  <children>
    <SplitPane id="main-split-pane" dividerPositions="0.25" focusTraversable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="-1.0" prefWidth="-1.0" style="" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
      <items>
        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" style="" />
        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
      </items>
    </SplitPane>
  </children>
  <padding>
    <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
  </padding>
  <stylesheets>
    <URL value="@main-view.css" />
  </stylesheets>
</AnchorPane>

我正在使用以下 CSS:

#main-split-pane {
    -fx-border-style: none;
    -fx-border-color: blue;
    -fx-border-width: 25;
}

它给了我这样的窗口:

我玩过这里显示的 CSS 设置,但有一些事情我无法理解:

  1. 我用红色箭头标记的边界来自哪里?
  2. 为什么设置-fx-border-stylenone导致-fx-border-color被忽略,而-fx-border-width仍然对事物的外观有影响(如填充)?
4

2 回答 2

47

解决方案 - 如何从拆分窗格中删除边框

如果您不想显示边框,请覆盖 -fx-box-border 颜色定义:

split.setStyle("-fx-box-border: transparent;");

删除了边框的拆分窗格

香蕉船

示例代码

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class SplitPaneBorderRemover extends Application {
  public static void main(String[] args) throws Exception { launch(args); }
  @Override public void start(final Stage stage) throws Exception {
    StackPane r1 = new StackPane();
    r1.setPrefSize(200, 150);
    r1.setStyle("-fx-background-color: palegreen;");
    
    StackPane r2 = new StackPane();
    r2.setPrefSize(200, 150);
    r2.setStyle("-fx-background-color: coral;");
    
    SplitPane split = new SplitPane();
    split.getItems().setAll(
      r1, r2
    );
    split.setStyle("-fx-box-border: transparent;");
    
    StackPane layout = new StackPane();
    layout.getChildren().setAll(split);
    layout.setStyle("-fx-padding: 20px; -fx-background-color: cornsilk");
    
    stage.setScene(new Scene(layout));
    stage.show();
  }
}

附加问题的答案

我用红色箭头标记的边界来自哪里?

它是默认 css 样式表(JavaFX 2.2的 caspian.css或Java 8 的 modena.css)中的背景样式。

为什么将 -fx-border-style 设置为 none 会导致 -fx-border-color 被忽略,而 -fx-border-width 仍然对事物的外观有影响(如填充)?

因为拆分窗格的边框是使用背景定义而不是边框​​定义来显示的。所有默认的 JavaFX 控件 css 样式都以这种方式工作。他们设置多个叠加背景来完成边框技术,而不是通过设置显式边框属性。

了解答案的工作原理

虽然这个答案实际上只是一个简单的衬线,但我会花一些时间在这里解释它为什么有效。对不起,如果这个解释使答案膨胀。那些已经知道这些信息的人可以忽略这部分答案。

我仍然无法理解这个概念

花一些时间阅读 JavaFX css 参考指南,我知道有点枯燥,但如果您想了解 JavaFX css 样式,则必须阅读。

还有一个css 的官方 Oracle 教程,但它不会像阅读 css 参考和学习我之前链接的默认样式表那样教你。

我从 css 参考中提取了相关语句并在此处引用它们:

JavaFX 具有丰富的 CSS 扩展集,以支持颜色派生、属性查找以及单个节点的多种背景颜色和边框等功能。这些功能为开发人员和设计人员增加了重要的新功能,并在本文档中进行了详细描述。

设置为透明以移除边框的 -fx-box-border 根本不是真正的边框,它是已应用于拆分窗格的多个背景之一的查找颜色。

通过查找颜色,您可以引用在当前节点或其任何父节点上设置的任何其他颜色属性。这是一个非常强大的功能,因为它允许在场景中指定通用调色板,然后在整个应用程序中使用。如果您想更改其中一种调色板颜色,您可以在场景树中的任何级别执行此操作,它将影响该节点及其所有后代。查找到的颜色在应用之前不会查找,因此它们是实时的,并对可能发生的任何样式更改做出反应,例如在运行时用节点上的“样式”属性替换调色板颜色。

在以下示例中,所有按钮的所有背景颜色都使用查找颜色“abc”。

.root { abc: #f00 }

.button { -fx-background-color: abc }

Java 8 modena.css 样式的 -fx-box-border 的默认定义是:

/* A little darker than -fx-color and used to draw boxes around objects such
 * as progress bars, scroll bars, scroll panes, trees, tables, and lists.
 */
-fx-box-border: ladder(
    -fx-color,
    black 20%,
    derive(-fx-color,-15%) 30%
);

拆分窗格的默认样式是“Box Like Thing”:

/* ====   BOX LIKE THINGS   ================================================= */

.scroll-pane,
.split-pane,
.list-view,
.tree-view,
.table-view, 
.tree-table-view,
.html-editor {
    -fx-background-color: -fx-box-border, -fx-control-inner-background;
    -fx-background-insets: 0, 1;
    -fx-padding: 1;
}
. . .
/* ones with grey -fx-background not lighter -fx-control-inner-background */
.scroll-pane,
.split-pane {
    -fx-background-color: -fx-box-border, -fx-background;
}

因此,分析 css,您可以看到,对于未聚焦的拆分窗格,定义了两个背景(因为 .split-pane 的 -fx-background-color 的最新或最具体的定义赢得了 css 的奇怪应用程序规则)。内部背景颜色为 -fx-background 并插入一个像素。外部背景颜色为 -fx-box-border 且未插入。拆分窗格的填充设置为一个像素。这可以防止拆分窗格内容覆盖它周围的一个像素边框。

此答案中的解决方案通过使用 setStyle 方法覆盖代码中专门针对给定拆分窗格实例的查找颜色定义来工作。通过将 -fx-box-border 设置为透明(尽管可能 null 也可以同样使用并且可能更有效),边框被设置为不可见(即使它仍然存在并且它的填充仍然存在在 1 像素的 CSS 中)。

如果需要,对 css 的进一步修改(通过应用您自己的用户样式表来覆盖默认的拆分窗格样式类)可以删除这个像素填充:

.split-pane {
    -fx-background-color: -fx-control-inner-background;
    -fx-background-insets: 0;
    -fx-padding: 0;
}

现在边框的所有痕迹都消失了,您的内容可以自由地填充拆分窗格的整个区域,包括边框曾经所在的 1 像素区域。我更喜欢将 -fx-box-border 设置为透明的最小更改,因为这样您的用户样式定义很小,并且不会从默认样式中详细说明。

例如,设置 -fx-box-border: red; 你会在拆分窗格周围得到一个 1px 的红色边框。

是的,这是因为 -fx-box-border 颜色着色的默认背景区域只有 1 个像素宽,而您刚刚明确地将像素颜色设置为红色。

我假设它是填充组件上的框边框。

不,如上所述,原因是因为背景 -fx-box-border 距区域边缘 0 像素的插图,而内部背景 -fx-background-color 距区域边缘 1 像素的插图,留下 1 个像素宽度,用 -fx-box-border 着色。在这种情况下,-fx-padding 所做的所有工作都是确保您的拆分窗格内容不会绘制在拆分窗格的 1 像素外部背景上。

然后设置 -fx-padding: 5; 在分裂。红色框边框消失,出现另一个灰色边框。

“灰色边框”始终存在 - 它是在拆分窗格 css 样式中定义的第二个内部背景(-fx-background 之一)。默认 -fx-background 颜色为灰色。通过将 -fx-padding 设置为 5,您是说将拆分窗格的内容从拆分窗格区域的外边缘插入 5 个像素。这允许默认背景显示出来。

如果您的内容有一些透明区域并且没有填满拆分窗格的整个可用区域,那么您也会在这些透明区域中看到灰色 -fx-background-color 颜色显示。

如果您想要在您的内容周围以 -fx-box-border 颜色实现 5 像素边框,那么您需要调整填充和边框插图,例如:

.split-pane {
    -fx-background-color: -fx-box-border, -fx-control-inner-background;
    -fx-background-insets: 0, 5;
    -fx-padding: 5;
}

如果对大型应用程序的填充、背景插入、css 样式派生规则等进行手动分析似乎令人生畏,请知道有工具支持可以帮助理解场景图结构和 css 应用程序。使用的工具是用于设计时 css 分析的SceneBuilder的 css 分析器和用于运行时场景图和 css 分析的 ScenicView。

于 2013-05-31T19:45:35.560 回答
1

如果要删除拆分窗格周围的边框,但保留分隔线的边框,请执行以下操作:

.split-pane {
  -fx-background-color: transparent, -fx-background;
}
于 2020-03-12T01:32:22.740 回答