带有多个开放式窗格的JavaFX手风琴

时间:2013-03-13 13:09:29

标签: javafx accordion

是否可以在JavaFX中使用带有1个以上打开窗格的手风琴?

3 个答案:

答案 0 :(得分:33)

不,JavaFX 2.2 Accordion一次只能有一个打开的窗格。

我为一个功能创建了一个增强请求(JDK-8090554 StackedTitledPanes control),允许您一次打开手风琴中的多个窗格,但功能请求目前尚未实现。

与此同时,您可以通过创建多个TitledPane实例并将其放在VBox中来轻松构建类似的控件。

private VBox createStackedTitledPanes() {
  final VBox stackedTitledPanes = new VBox();
  stackedTitledPanes.getChildren().setAll(
    new TitledPane("Pane 1",  contentNode1),
    new TitledPane("Pane 2",  contentNode2),
    new TitledPane("Pane 3",  contentNode3)
  );
  ((TitledPane) stackedTitledPanes.getChildren().get(0)).setExpanded(true);

  return stackedTitledPanes;
}

如有必要,您可以将包含您的窗格的VBox打包到ScrollPane中,以便所有展开的窗格的内容在其区域溢出可用区域时可以使用。

我创建了一个sample solution(图标是来自http://www.fasticon.com的链接软件)。

fishyfishy

答案 1 :(得分:0)

我的要求略有不同

  1. 手风琴可以扩展或管理嵌入视图的视图空间
  2. 整个视图可以放入滚动视图
  3. 如果手风琴是固定大小的话,每个方框都会完全展开到整个视图的大小,或者如果它不是固定视图,它会扩展到内容的大小。
  4. 虽然在我的情况下,我无法完成全部3.并且测试2.我能够提出以下修复:

    1)使用内置VBox的ScrollPane,里面有TitledWindows。 2)确保您的TitledPanes设置为 VBox.grow =“SOMETIMES”。 3)添加一个VBox作为最后一个元素并设置 VBox.vgrow =“ALWAYS” - 这会将TitledPanes推到最小尺寸。其他人都提供了Code示例,如果你想使用fxml,或者不想使用Java,那么直接使用这些元素同样适用(使用SceneBuilder生成):

    <ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
         <content>
            <VBox fx:id="leftVBox" maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="100.0">
               <children>
                  <TitledPane fx:id="titledPanelOne" animated="false" expanded="false" style="-fx-background-color: red;" text="Pane One" VBox.vgrow="SOMETIMES">
                     <content>
                        <ListView fx:id="listViewOne" maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" />
                     </content>
                  </TitledPane>
                  <TitledPane fx:id="titledPanelTwo" animated="false" expanded="false" style="-fx-background-color: green;" text="Pane Two" VBox.vgrow="SOMETIMES">
                     <content>
                        <ListView fx:id="listViewTwo" maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" />
                     </content>
                  </TitledPane>
                  <VBox prefHeight="0.0" prefWidth="0.0" VBox.vgrow="ALWAYS" />
               </children>
            </VBox>
         </content>
     </ScrollPane>
    

    4)虽然这确实可以让您堆叠的盒子彼此独立地展开/收缩,但这并不能解决您的盒子没有正确调整其内容大小的问题(例如,如果您嵌入了列表视图如上例所示),所以当你有足够的屏幕空间时,你现在必须滚动很多。解决方案?需要一些Java。

    要实现此修复,我们首先将TitledPane的maxHeightProperty()绑定到外部VBox的heightProperty()

    public class Controller implements Initializable {
      //... controller code
      @Override
      public void initialize(URL location, ResourceBundle resources) {
        //...
        variablesViewPane.maxHeightProperty().bind(leftVBox.heightProperty());
        historyViewPane.maxHeightProperty().bind(leftVBox.heightProperty());
      }
    }
    

    我们绑定到每个窗格的expandedProperty(),并动态绑定和取消绑定prefHeighProperty()

    private static void bindExpanded(TitledPane pane, ReadOnlyDoubleProperty prop) {
      pane.expandedProperty().addListener((observable, oldValue, newValue) -> {
        if(newValue) {
          pane.prefHeightProperty().bind(prop);
        } else {
          pane.prefHeightProperty().unbind();
          pane.prefHeightProperty().set(0);
        }
      });
    

    }

    如果我们被展示,我们要求与VBox一样大,如果我们没有显示,我们要求尽可能小。以这种方式做事的好处是布局然后根据当前显示的TitledPanes的数量自动计算可用高度 - 这导致了我们想要的行为。

    我在这里详细介绍:

    http://sebastianaudet.com/blog/playing-with-javafx/

答案 2 :(得分:0)

将现有的最佳答案与简化内容结合起来,您可以通过在ScrollPane VBox中创建几个带标题的面板,然后将max-height属性与侦听器绑定来复制多重打开的手风琴(在XML上窗格即使折叠也会保留空间)

<ScrollPane fitToHeight="true" fitToWidth="true">
    <AnchorPane id="Content">
        <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
            <!-- Setting maxHeight="Infinity" to all makes them all grow as we want, but then they get spaces between, when collapsed (so we do it in code) -->
            <TitledPane fx:id="pane1" animated="false" VBox.vgrow="ALWAYS" expanded="false" text="Pane 1">...</TitledPane>
            <TitledPane fx:id="pane2" animated="false" VBox.vgrow="ALWAYS" maxHeight="Infinity" text="Pane 2 (starts expanded)">...</TitledPane>
            <TitledPane fx:id="pane3" animated="false" VBox.vgrow="ALWAYS" expanded="false" text="Pane 3">...</TitledPane>
        </VBox>
    </AnchorPane>
</ScrollPane>

注意:您需要为每个窗格调用此方法:

pane1.expandedProperty().addListener((observable, oldValue, newValue) -> {
    //make it fill space when expanded but not reserve space when collapsed
    if (newValue) {
        pane1.maxHeightProperty().set(Double.POSITIVE_INFINITY);
    } else {
        pane1.maxHeightProperty().set(Double.NEGATIVE_INFINITY);
    }
 });