如何在JavaFX中消除分割面板周围的边框?

11

我正在使用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-style 设置为 none 会导致 -fx-border-color 被忽略,而 -fx-border-width 仍然会影响东西的外观(如填充)?

fx-padding:0 怎么样? - stark
@stark 改变分割窗格的填充似乎没有任何作用。将 -fx-border-style: none;-fx-border-color 设置为任何值似乎可以解决问题,但这对我来说完全没有意义。 - Ryan J
2个回答

48

解决方案 - 如何从分割面板中移除边框

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

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

取消边框的分隔窗格

bananasplit

示例代码

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样式表中的背景样式(caspian.css for JavaFX 2.2modena.css for Java 8))。

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

因为分割窗格的边框是使用背景定义而不是边框定义来显示的。所有默认的JavaFX控件CSS样式都是这样工作的。它们设置多个重叠的背景来实现边框技术,而不是通过设置显式边框属性来实现。

理解答案的工作原理

虽然这个答案只是一个简单的一行代码,但我会在这里花些时间解释它为什么有效。如果这个解释让答案显得臃肿,对不起。那些已经了解这些信息的人可以忽略这部分答案。

我仍然有困难理解这个概念

花点时间阅读JavaFX css参考指南,我知道它有点枯燥,但如果你想了解JavaFX css样式,它是必须阅读的。

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

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

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

“-fx-box-border”被设置为透明以移除边框,实际上它并不是一个边框,而是应用于分割窗格的多个背景之一的查找颜色。
使用查找颜色,可以引用当前节点或其任何父节点上设置的任何其他颜色属性。这是一个非常强大的功能,因为它允许在场景中指定通用调色板,然后在整个应用程序中使用。如果要更改其中一个调色板颜色,可以在场景树的任何级别上这样做,它将影响该节点及其所有子代。查找颜色直到应用时才会被查找,因此它们是实时的,并且会对可能发生的任何样式更改做出反应,例如使用节点上的“style”属性在运行时用调色板颜色替换。
在下面的示例中,所有按钮的背景颜色都使用了查找颜色“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 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,定义了两个背景(作为 .split-pane 的最新或最具体的 -fx-background-color 定义,因为 CSS 的奇怪应用规则)。 内部背景颜色为 -fx-background,并向内缩进一个像素。 外部背景颜色为 -fx-box-border,不缩进。 Split pane 的填充设置为一个像素。 这可以防止分割窗格内容覆盖其周围的一个像素边框。
此答案中的解决方案通过在代码中针对给定的 splitpane 实例覆盖查找颜色定义来使用 setStyle 方法工作。 通过将 -fx-box-border 设置为透明(虽然可能同样可以使用 null 并且可能更有效),边框设置为不可见(即使它仍然存在并且 css 中的填充仍为 1 像素)。
通过应用自己的用户样式表以覆盖默认的 split-pane 样式类,可以进一步修改 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;设置为红色,您将获得一个围绕分割窗格的1像素红色边框。
是的,这是因为-fx-box-border颜色所着色的默认背景区域仅为1像素宽,您刚刚明确将像素颜色设置为红色。
我假设这是填充组件上的框边界。
不是的,如上所述,原因是-fx-box-border背景与区域边缘的内部距离为0像素,而内部背景-fx-background-color从区域边缘向内缩进1像素,留下1像素宽度用-fx-box-border进行着色。在这种情况下,所有-fx-padding所做的就是确保您的分割窗格内容不会绘制在分割窗格的1像素外部背景上。
然后在split上设置-fx-padding: 5;。红色框边消失,另一个灰色边框出现。"灰色边框"一直存在-它是在split-pane 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 应用程序。使用的工具是 SceneBuilder 的 CSS 分析器 用于设计时 CSS 分析和 ScenicView 用于运行时场景图和 CSS 分析。

我会接受这个答案,因为它有效,但我仍然有理解这个概念的困难。例如,设置-fx-box-border: red;,你会得到一个1像素的红色边框围绕分割窗格。然后在split上设置-fx-padding: 5;。红色盒子边框消失了,另一个灰色边框出现了。我认为这是填充组件上的盒子边框,但是让填充组件添加边框似乎非常令人困惑。填充与组件的边框有什么关系? - Ryan J
1
更新答案以解释涉及到的一些JavaFX css概念。我之前不想写太多来解释一个简短的答案。虽然我不知道如何在提供足够的解释的同时使其更加简洁,但仅提供一行答案可能有点神奇。 - jewelsea
1
插图如何显示默认背景使我感到困惑。真希望我能为这个绝妙的回答投多一票。谢谢! - Ryan J

1
如果您想移除分割窗格周围的边框,但保留分隔符的边框,请按照以下步骤操作:
.split-pane {
  -fx-background-color: transparent, -fx-background;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接