10

我在互联网上的任何地方都找不到关于此的答案。

我有一个必须具有可折叠面板的应用程序,因此 Java FX 中的 TitledPane 和 Accordion 设置是自然的选择。

在应用程序中,我需要在容器折叠时为其自定义标题。我在 TitledPane 的 css 文档中看到,标题实际上是一个 HBox 和各种其他组件。

http://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html#titledpane

我想访问此组件并将其替换为自定义组件。

我一直在使用 TitledPane api 的 setGraphic 函数和 setContentDisplay 到 GraphicOnly。使用自定义组件。但是,我无法让它正确渲染。我在移除箭头和移除箭头占用的空间时遇到了问题。

有关所需外观的屏幕截图及其实际外观,请参阅下面的链接。

http://tinypic.com/r/s1pxfn/6

如何删除箭头并删除填充?

4

4 回答 4

24

TitledPane 是带标签的,因此您可以在侦听器中在其上设置图形或绑定到扩展属性。

更改背景颜色等(包括覆盖 :focused 伪类的样式)可以通过 css 完成(例如,请参阅 jfxrt.jar 中caspian.css样式表的 TitledPane 部分)。

如果您需要基于代码访问 TitledPane 的子组件,您可以在 TitledPane 添加到舞台上显示的场景后使用查找功能。

adminPane.lookup(".arrow").setVisible(false);

我建议在尝试查找之前尝试基于图形/css 样式表的方法。

如果您不需要 Labeled 来显示文本,则将其设置为仅显示图形

titledPane.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

这是一些示例代码,它在没有自定义标题的 TitledPane 旁边显示带有自定义标题的 TitledPane。

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

/** http://stackoverflow.com/questions/11765436/how-to-change-header-component-in-titledpane-in-javafx */
public class TitledPaneCustomization extends Application {
  public static void main(String[] args) { launch(args); }

  @Override public void start(Stage primaryStage) {
    TitledPane adminPane = new TitledPane("Administration", 
      VBoxBuilder.create().style("-fx-padding: 10").spacing(10).children(
        ButtonBuilder.create().text("Admin Client").maxWidth(Double.MAX_VALUE).build(),
        ButtonBuilder.create().text("Admin User").maxWidth(Double.MAX_VALUE).build()
      ).build()            
    );
    adminPane.setAnimated(false);
    adminPane.getStyleClass().add("admin");
    Node open   = HBoxBuilder.create().spacing(5).children(
      new Circle(4, 4, 8, Color.FORESTGREEN),
      new Rectangle(50, 16, Color.AQUAMARINE)
    ).build();
    Node closed = HBoxBuilder.create().spacing(5).children(
      new Circle(4, 4, 8, Color.GOLDENROD),
      new Rectangle(50, 16, Color.AQUAMARINE)
    ).build();

    adminPane.graphicProperty().bind(
      Bindings
        .when(adminPane.expandedProperty())
          .then(open)
          .otherwise(closed)
    );
    adminPane.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

    TitledPane viewPane = new TitledPane("View", 
      VBoxBuilder.create().style("-fx-padding: 10").spacing(10).children(
        ButtonBuilder.create().text("View Client").maxWidth(Double.MAX_VALUE).build(),
        ButtonBuilder.create().text("View User").maxWidth(Double.MAX_VALUE).build()
      ).build()            
    );
    viewPane.setAnimated(false);

    VBox errorPane = VBoxBuilder.create().style("-fx-padding: 10").spacing(10).children(
      new Label("500: Aug 8, 12:15pm"), 
      new Label("404: Aug 7, 3:27am")
    ).build();
    Label nErrors = new Label();
    nErrors.getStyleClass().add("nerrors");
    nErrors.textProperty().bind(Bindings.size(errorPane.getChildren()).asString());

    TitledPane connectivityPane = new TitledPane(
      "",      
      errorPane
    );
    Label connectivityErrorLabel = new Label("CONNECTIVITY ERROR");
    connectivityErrorLabel.getStyleClass().add("connectivityErrorLabel");
    connectivityPane.getStyleClass().add("connectivity");
    connectivityPane.setAnimated(false);
    connectivityPane.setGraphic(
      HBoxBuilder.create().spacing(2).alignment(Pos.CENTER).styleClass("header").children(
        nErrors,    
        new ImageView(
          new Image(
            "http://openiconlibrary.sourceforge.net/gallery2/open_icon_library-full/icons/png/48x48/actions/network-disconnect-2.png",
            0, 24, true, true
          )
        ),
        connectivityErrorLabel
      ).build()
    );

    HBox layout = new HBox(10);
    layout.setStyle("-fx-padding: 10; -fx-background-color: cornsilk;");
    layout.getChildren().addAll(adminPane, viewPane, connectivityPane);
    layout.setPrefHeight(150);
    layout.getStylesheets().add(this.getClass().getResource("titledpanecustomization.css").toExternalForm());
    primaryStage.setScene(new Scene(layout));
    primaryStage.show();

    Node arrow = adminPane.lookup(".arrow");
    arrow.setVisible(false);
    arrow.setManaged(false);

    // translate the titledpane arrow and header so that the arrow is displayed to right of the header.
    Pane connectivityArrow = (Pane) connectivityPane.lookup(".arrow");
    connectivityArrow.translateXProperty().bind(
      connectivityPane.widthProperty().subtract(connectivityArrow.widthProperty().multiply(2))
    );
    Pane connectivityTitle = (Pane) connectivityPane.lookup(".header");
    connectivityTitle.translateXProperty().bind(
      connectivityArrow.widthProperty().negate()
    );
  }
}

还有一些与之配套的CSS:

/** titledpanecustomization.css place in same build directory as TitledPaneCustomization.java 
    and ensure build system copies it to the output classpath. */
.admin .titled-pane > .title {
  -fx-background-color: blue, yellow, linear-gradient(to bottom, derive(coral, +50%), coral);
}

.connectivity {
  -fx-text-fill: white;
}

.nerrors {
  -fx-background-color: derive(-fx-focus-color, -15%);
  -fx-padding: 5 8 5 8;
  -fx-text-fill: white;
}

.connectivityErrorLabel {
  -fx-text-fill: white;
  -fx-padding: 0 40 0 3; 
}

.connectivity .titled-pane > .title {
  -fx-background-color: -fx-box-border, -fx-inner-border, -fx-body-color;
  -fx-background-insets: 0, 1, 2;
  -fx-background-radius: 0 0 0 0, 0 0 0 0, 0 0 0 0;
  -fx-padding: 0.166667em 1.166667em 0.25em 0; /* 2 14 3 0 */
  -fx-color: -fx-focus-color;
}

.connectivity .titled-pane > .title > .arrow-button .arrow {
  -fx-background-color: white;
}

示例自定义 TitledPane

于 2012-08-01T20:02:37.907 回答
3

(移动问题的答案)

这是答案:

要删除箭头,请添加以下 CSS 声明:

.titled-pane > .title > .arrow-button .arrow{
    -fx-shape: "";
}

上面的 CSS 片段将删除箭头,但箭头的空间仍然被占用。这真的很棘手,我在互联网上的任何地方都找不到它的文档,但我应用了这个 CSS 语句,它消除了箭头上的间隙。

.titled-pane > .title{
   -fx-padding: 0 0 0 -4;
}

这可能不是最好的解决方案,但它是满足我需求的解决方案。

于 2016-04-14T06:11:42.043 回答
0

在 2018 年底的今天,这些解决方案中没有一个适用于 JDK 1.8 的 JavaFX。所以我正在研究一个简单的解决方案。您可以将此方法复制到实用程序类中:

public static boolean hideArrow(TitledPane pane) {
    Node arrowButton = pane.lookup(".arrow-button");
    if (arrowButton == null) {
        return false;
    }
    // I don't know how with this the arrow space disappears...., but it does
    arrowButton.setStyle("-fx-background-color: black;");
    Parent titleRegion = arrowButton.getParent();
    titleRegion.addEventFilter(MouseEvent.ANY, MouseEvent::consume);
    titleRegion.setCursor(Cursor.DEFAULT);
    ((StackPane) titleRegion).getChildren().remove(arrowButton);
    return true;
}
于 2018-11-16T11:23:04.247 回答
-1

这是删除箭头的方法:

.titled-pane > .title > .arrow-button > .arrow{
    -fx-shape: null;
}
于 2014-07-24T12:35:34.273 回答