How do I get rid of the border around a split pane

2019-01-24 11:41发布

I'm using the JavaFX SceneBuilder, but I'll paste the FXML below since it's short. I have a very simple window with a split pane inside an anchor pane. Here is the 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>

I'm using the following CSS:

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

It gives me a windows like this:

I've played around with the CSS settings shown here, but there are a few things I'm having trouble understanding:

  1. Where is the border I've marked with the red arrow coming from?
  2. Why does setting the -fx-border-style to none cause the -fx-border-color to be ignored while the -fx-border-width still has an effect (like padding) on how things look?

1条回答
该账号已被封号
2楼-- · 2019-01-24 12:20

Solution - How to remove a border from a Split Pane

Override the -fx-box-border color definition if you don't want the border to show:

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

Split Pane with Border Removed

bananasplit

Sample Code

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();
  }
}

Answers to Additional Question

Where is the border I've marked with the red arrow coming from?

It's a background style in the default css stylesheet (caspian.css for JavaFX 2.2 or modena.css for Java 8)).

Why does setting the -fx-border-style to none cause the -fx-border-color to be ignored while the -fx-border-width still has an effect (like padding) on how things look?

Because the border of split pane is displayed using a background definition rather than border definition. All default JavaFX control css styles work this way. They set multiple overlaid backgrounds to accomplish border techniques rather than by setting an explicit border attribute.

Understanding How the Answer Works

Although this answer is really just a simple one liner, I'll take some time to explain here why it works. Sorry if this explanation bloats the answer. Those who already know this information can ignore this part of the answer.

I'm still having trouble understanding the concept

Spend some time reading the JavaFX css reference guide, a bit dry I know, but essential reading if you want to understand JavaFX css styling.

There is also an official Oracle tutorial for css, but it's not going to teach you as much as reading the css reference and studying the default style sheets I linked earlier.

I extracted relevant statements from the css reference and quoted them here:

JavaFX has a rich set of extensions to CSS in support of features such as color derivation, property lookup, and multiple background colors and borders for a single node. These features add significant new power for developers and designers and are described in detail in this document.

The -fx-box-border which is set to transparent to remove the border, is not really a border at all, it is a looked up color that has been applied to one of multiple backgrounds for the split-pane.

With looked-up colors you can refer to any other color property that is set on the current node or any of its parents. This is a very powerful feature, as it allows a generic palette of colors to be specified on the scene then used thoughout the application. If you want to change one of those palette colors you can do so at any level in the scene tree and it will affect that node and all its decendents. Looked-up colors are not looked up until they are applied, so they are live and react to any style changes that might occur, such as replacing a palette color at runtime with the "style" property on a node.

In the following example, all background color of all buttons uses the looked up color "abc".

.root { abc: #f00 }

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

The default definition for -fx-box-border for the Java 8 modena.css style is:

/* 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%
);

The default styling for a split-pane is as a "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;
}

So, analyzing the css, you can see that, for an unfocused split-pane there are two backgrounds defined (as the latest or most specific definition of -fx-background-color for .split-pane wins css's weird application rules). The inner background is colored as -fx-background and is inset one pixel. The outer background is colored as -fx-box-border and is not inset. Padding for the split pane is set to one pixel. This prevents the split pane content from overwriting the one pixel border around it.

The solution in this answer works by overriding the look-up color definition in code specifically for a a given splitpane instance by using the setStyle method. By setting the -fx-box-border to transparent (though perhaps null could have been used equally as well and might be more efficient), the border is set to be not visible (even though it is still there and the padding for it remains in the css at 1 pixel).

Further modification of the css (by applying your own user stylesheet to override the default split-pane style class) could remove this one pixel padding if desired:

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

Now all trace of the border is gone and your content is free to fill the entire area of the split pane including the 1 pixel area where the border used to be. I prefer the minimal change of just setting the -fx-box-border to transparent though because then your user style definitions are small and don't detail a lot from the default style.

For example, set -fx-box-border: red; and you'll get a 1px red border around the split pane.

Yep, that's because the default background area the -fx-box-border color is coloring is only 1 pixel wide and you have just explicitly set the pixel color to red.

I assume it's the box-border on the padding component.

No, as described above the reason is because the background the -fx-box-border an inset of 0 pixels from the edge of the region and the inner background -fx-background-color is inset 1 pixel from the edge of the region, leaving 1 pixel width colored with the -fx-box-border. All the -fx-padding is doing in this instance is ensuring that your split pane content does not draw over the 1 pixel outer background for the split-pane.

Then set -fx-padding: 5; on split. The red box-border disappears and another gray border shows up.

The "gray border" was always there - it's the second, inner background defined in the split-pane css style (the -fx-background one). And the default -fx-background color is gray. By setting -fx-padding to 5 you are saying to inset the content of the split pane 5 pixels from the outside edge of the splitpane region. This allows the default background to show through.

If your content had some transparent areas and did not fill the whole available region of the split-pane, then you would also have seen this gray -fx-background-color color show through in those transparent areas.

If what you wanted was to achieve a 5 pixel border around your content in -fx-box-border color then you would need to adjust both the padding and the border insets, for example:

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

If the manual analysis of the padding, background insets, css style derivation rules, etc for a large application seems like it would be daunting, know that there is tool support to help understand both the scene graph structure and css application. The tools to use are SceneBuilder's css analyzer for design time css analysis and ScenicView for runtime scenegraph and css analysis.

查看更多
登录 后发表回答