1

I have a view with two TitledPanes in a SplitPane oriented vertically. I want when I collapse one of them, the other one to be resized to the Scene's height. Here is the code of my .fxml file:

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<BorderPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:id="pane"
            fx:controller="stackoverflow.three.Controller">
    <center>
        <SplitPane fx:id="split" orientation="VERTICAL">
            <TitledPane fx:id="first" text="First">
                <TableView>
                    <columns>
                        <TableColumn text="Test"/>
                    </columns>
                </TableView>
            </TitledPane>
            <TitledPane fx:id="second" text="Second">
                <TableView>
                    <columns>
                        <TableColumn text="Test"/>
                    </columns>
                </TableView>
            </TitledPane>
        </SplitPane>
    </center>
</BorderPane>

Here are some sreenshots: The initial state: Initial State When the first is collapsed: First collapsed

As you can see there is a gap at the bottom of the view, if I collapse the first one, but I don't want that gap.

I've tried to se the maxHeight for example to Infinity, but then the auto move up to the firs one is not working... Any ide what can I do?

Sunflame
  • 2,993
  • 4
  • 24
  • 48
  • try setting `VBox.vgrow="always"` on both of your TitledPanes. – MMAdams Nov 21 '17 at 14:59
  • But there I have a `SplitPane`, I cannot change to `VBox` since I need the resizing by "hands", that has the `SplitPane` – Sunflame Nov 21 '17 at 16:12
  • You can wrap your TitledPanes in VBoxes inside the SplitPane. – MMAdams Nov 21 '17 at 16:25
  • Yes but then the second pane doesn't enlarges to the first one if I collapse the first. – Sunflame Nov 21 '17 at 16:36
  • huh. you're right, in your original code it does enlarge some, but it still leaves a gap, I wonder why that is. I may play with it later and come up with a real answer, but I would suggest wrapping your titled panes in different types of regions and seeing how that changes their layout. – MMAdams Nov 21 '17 at 16:57

4 Answers4

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

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>

<BorderPane fx:id="pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="stackoverflow.three.Controller">
    <center>
      <VBox prefHeight="800.0">
         <children>
               <TitledPane fx:id="first" text="First">
                  <content>
                      <TableView prefHeight="2000.0">
                          <columns>
                              <TableColumn text="Test" />
                          </columns>
                      </TableView>
                  </content>
               </TitledPane>
               <TitledPane fx:id="second" text="Second">
                  <content>
                      <TableView prefHeight="2000.0">
                          <columns>
                              <TableColumn text="Test" />
                          </columns>
                      </TableView>
                  </content>
               </TitledPane>
         </children>
      </VBox>
    </center>
</BorderPane>
Tadasbub
  • 196
  • 7
  • As I mentioned in the question, I've tried to se a maxHeight for the panes but then the second pane doesn't enlarge to the first one after I collapse the fist. – Sunflame Nov 22 '17 at 08:36
  • But you are collapsing the TitledPane, I do not see why the SplitPane would resize. SplitPane is a container which will not change its size based on contents. That is not the purpose of it. The only thing I can see you doing is on collapse action you can resize scrollpane programatically adjusting divider's position from the code. – Tadasbub Nov 22 '17 at 13:54
  • I don't want to resize the container(the `SplitPane`) I just want to get rid of "empty spaces" when I expand/collapse a pane, so for example if I collapse the fist one I want to the second pane cover the empty space at the bottom of the view. Of course when both are collapsed there is empty space, after them but that is ok. – Sunflame Nov 22 '17 at 14:02
  • I would need something similar like here: https://stackoverflow.com/questions/12510858/titledpane-event, but I'm still experimenting how can I do it. – Sunflame Nov 22 '17 at 14:03
  • Updated the fxml a bit, take a look, does this do the trick for you? – Tadasbub Nov 22 '17 at 14:19
  • It almost works, but now I lost the resizing, so I cannot drag the separator like I could in the SplitPane – Sunflame Nov 22 '17 at 14:22
  • Well, yes, but that is what I am trying to say - SplitPane is used to resize containers on both sides of the Divider. The contents of the containers, their shape and positioning does not affect SplitPane. A custom fx element could be build for that purpose I suppose. Sorry but as it is, SplitPane is never going to work that way out of a box (again, you can programmatically change it from your controller). If you want to help user see tables better, maybe you want to adjust TableView height proportionally based on number of rows. – Tadasbub Nov 22 '17 at 14:29
  • Yeah, maybe I can implement some drag functionality for the separator, thank you very much, I think I am quite close to the solution so I'm accepting your answer – Sunflame Nov 22 '17 at 14:46
2

I had a similar problem and solved it by setting maxHeight to MAX_VALUE for both TitledPanes. No listeners and no wrappers (vbox, ...) are necessary in my case. I'm using openjfx 11.0.1.

ruu
  • 51
  • 1
  • 6
0

OK, here is a plan B:

Have fxml with a SplitPane

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

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>

<BorderPane fx:id="pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="stackoverflow.three.Controller">
    <center>
      <SplitPane dividerPositions="0.5" orientation="VERTICAL" prefHeight="800.0">
         <items>
               <TitledPane fx:id="first" text="First">
                  <content>
                      <TableView prefHeight="2000.0">
                          <columns>
                              <TableColumn text="Test" />
                          </columns>
                      </TableView>
                  </content>
               </TitledPane>
               <TitledPane fx:id="second" text="Second">
                  <content>
                      <TableView prefHeight="2000.0">
                          <columns>
                              <TableColumn text="Test" />
                          </columns>
                      </TableView>
                  </content>
               </TitledPane>
         </items>
      </SplitPane>
    </center>
</BorderPane>

to both TitledPane objects add listener to their boolean expanded property

expanded.addListener(new ChangeListener<Boolean>() {
     @Override
     public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
         resizeSplitPane();
     }
 });

private void resizeSplitPane(){
   // reposition split pane divider here depending on the status of both 
   // TableViews
   if(!tableView1.isExpanded() && tableView2.isExpanded()){
      splitPane.setDividerPosition(0, 0.1);
   }else if(tableView1.isExpanded() && !tableView2.isExpanded()){
      splitPane.setDividerPosition(0, 0.9);
   }else{
      splitPane.setDividerPosition(0, 0.5);
   }
}
Tadasbub
  • 196
  • 7
  • Did you tried it? Somehow the `splitPane.setDividerPositions(0.5);` doesn't sets the divider to the middle of the SplitPane. – Sunflame Nov 22 '17 at 15:07
  • I do not have access to my IDE right now, it was more of a pseudo code really, but try setDividerPosition(int dividerIndex, double percentage) as per https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/SplitPane.html – Tadasbub Nov 22 '17 at 15:17
  • I've solved it by adding a `setPrefHeight(-1)` for both before the if and in the else `setPrefHeight(split.getHeight() /2)` This is the closest solution. I miss one more thing: the smooth resize :) Now if i expand collapse, everything is resized correctly instantly, so doesn't keep the smooth expanding/collapsing. – Sunflame Nov 22 '17 at 15:25
  • Also it should be inverted the first and the second if, so the first is 0.1 and the second is 0.9 – Sunflame Nov 22 '17 at 15:26
  • Thanks, I updated the code, if you know the height of the collapsed pane in pixels (A) you would like to keep visible (because it should be constant based on TitledPane), you could also read the height (B) of the SplitPane and make it not arbitrarily selected 0.1, but (A/B) for first and (1-A/B) for second... – Tadasbub Nov 22 '17 at 15:35
  • 1
    I did this modifications and added to the else this: https://pastebin.com/LScXj3EL and it is working now as I expect. Thank you very much. – Sunflame Nov 23 '17 at 09:49
0

I managed to figure something out based on the answer here: Animate splitpane divider

    titledPane.expandedProperty().addListener((observable, oldValue, newValue) ->
    {
        double target = d1Orig;
        if( !newValue )
        {
            d1Orig = splitPane.getDividers().get(0);
            target = 0.0;
        }
        KeyValue keyValue = new KeyValue(splitPane.getDividers().get(0).positionProperty(), target);
        Timeline timeline = new Timeline(new KeyFrame(Duration.millis(500), keyValue));
        timeline.play();
    });

d1Orig is a double to save the original split pane position before collapsing.

maroc
  • 466
  • 2
  • 5