Featured Post

Applying Email Validation to a JavaFX TextField Using Binding

This example uses the same controller as in a previous post but adds a use case to support email validation.  A Commons Validator object is ...

Tuesday, June 30, 2015

Hacking a TitledPane for Resizing in JavaFX

I had some trouble getting a JavaFX TitledPane to resize the way I wanted, so I built my own TitledPane.  I didn't care about the collapse / expand functionality, so I just put an HBox containing a Label at the top of a VBox and copied the TitledPane styles.

This short video shows the desired resizing behavior.  "Console" is a view object that is shown or hidden based on an action taken from the main main.  Because it may contain a lot of information coming from a jarsigner.exe command, it both scrolls and resizes.  Other parts of the screen -- the GridPane, the status Label, and the MenuBar -- are fixed.

video


The resizing specification involves two settings: Vgrow (for the VBox children) and Resizable to Parent (for the SplitPane children).

Vgrow Setting

This is the hierarchy from SceneBuilder identifying the VGrow settings.  The MenuBar and the status Label are fixed so their values are set to Vgrow=NEVER.  The SplitPane is expected to grow and shrink with the overall window.  It is set to Vgrow=ALWAYS.

VGrow Settings for MenuBar, SplitPane, and Status Label

The main content is put in a SplitPane which divides the content into a fixed GridPane of form-like controls and a VBox containing a TextArea for free-form text that's wrapped in an AnchorPane.  The SplitPane will allow the GridPane to be resized when prompted to take some space away from the VBox.

Resizable With Parent Setting


The SplitPane children are configured as follows for the "Resizable With Parent" property.  The GridPane does not resize to the parent while the VBox does.

Resizable With Parent Specification

Faux TitledPane

I couldn't get the desired outcome with the TitledPane which remained fixed when I resized the window.  I suspect this has to do with the collapse / expand functionality which I'm disregarding anyway.  I'm driving the Console display off of the main menu.

So, I used a Label in an HBox to serve as the title object.  This was put at the top of a VBox.  The VBox "contents" are an AnchorPane holding a TextArea.

I want my fake TitledPane to look like the other TitledPanes in the app that do use the collapse functionality.  So, I went into the stylesheet in the jfxrt.jar file and pulled out the style for (.titled_pane > .title) and created my own style called .consoleTitle which I applied to the HBox.  Here is the style taken from the moderna.css file.


.consoleTitle {
    -fx-background-color:
        linear-gradient(to bottom,
            derive(-fx-color,-15%) 95%,
            derive(-fx-color,-25%) 100%
        ),
        -fx-inner-border, -fx-body-color;
    -fx-background-insets: 0, 1, 2;
    -fx-background-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0;
    -fx-padding: 0.3333em 0.75em 0.3333em 0.75em; /* 4 9 4 9 */

}

A lot of projects end up using their own stylesheets.  In the apps I use day-to-day -- GoToMeeting, SparxSystems Enterprise Architect, IntelliJ, Sage50 -- a distinct style seems to be preferred over a one-size-fits-all standard.  For example, alert popups don't look like standard system windows anymore with window titles removed, transparent "chrome", and custom X's for close.  So, you may have more access to your own TitledPane styling and can share that styling instead of the cut-and-paste that I did in this example.

6 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Or just use "maxHeight="Infinity":

    < TitledPane text="The Title" collapsible="false" maxHeight="Infinity">

    ReplyDelete
    Replies
    1. Thanks Fouad. This is a better solution. In this post, you can remove the HBox containing the Label that holds the title and the containing VBox. In its place, put a standard TitledPane. On the Layout panel in Scene Builder, set the Max Height value to MAX_VALUE of the TitledPane.

      If you notice a padding around the AnchorPane after this, and are trying to duplicate the UI in the video at the start of the post, set the -fx-padding of the AnchorPane to 0.

      Delete
    2. Thanks a lot, but Fouad's approach didn't work for me. In my case I just needed to set the minHeight and minWidth of the TitledPane as well as its inner TableView to zero.
      I think this is due to the fact that TitledPane doesn't inherit from Region like most of the JavaFX panes do.

      Delete
    3. However, in addition to setting minWidth/minHeight to zero I needed to set maxWidth/maxHeight to Infinity like Fouad suggested..

      Delete