Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I have to delve deep (looking through the JavaFX code itself), but I found a workable, but not ideal, solution.</p> <p>The problem basically boiled down to the fact that the TitledPane was not coded to support a horizontal content bias (where its min/preferred height is calculated based on its available width). So, even though its content, the Label, supports this functionality, its rendered mote by the TitledPane, which calculates its minimum and preferred dimensions without the consideration of the other, in which case the Label control simply requests a width and height necessary to display all its text on one line.</p> <p>To overrride this behavior, I had to override three functions, two in the TitledPane itself, and one in the TitlePane's default skin (which actually does the dimension calculations for TitledPane). First, I override the getContentBias return HORIZONTAL. Then, I override the getMinWidth to return 0. Finally, I update the skin's computePrefHeight function to take into account the available width when its asking its children how much height they need.</p> <p>Here is the code:</p> <pre><code>package nimrandsLibrary.fantasyCraft.characterBuilder import javafx.scene.control._ import javafx.scene.layout._ import javafx.scene._ class TiltedTextExample extends javafx.application.Application { private def createTitledPane(title: String) = { val titledPane = new HorizontalContentBiasTitledPane() titledPane.setText(title) val label = new Label("Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here. Some really long text here.") label.setWrapText(true) titledPane.setContent(label) titledPane.setExpanded(false) titledPane } def start(stage: javafx.stage.Stage) { val vBox = new VBox() vBox.getChildren().add(createTitledPane("Expand Me #1")) vBox.getChildren().add(createTitledPane("Expand Me #2")) vBox.getChildren().add(createTitledPane("Expand Me #3")) stage.setScene(new Scene(vBox, 300, 300)) stage.show() } } object TiltedTextExample extends App { javafx.application.Application.launch(classOf[TiltedTextExample]) } class HorizontalContentBiasTitledPane extends javafx.scene.control.TitledPane { override def getContentBias() = javafx.geometry.Orientation.HORIZONTAL override def computeMinWidth(height: Double) = 0 this.setSkin(new com.sun.javafx.scene.control.skin.TitledPaneSkin(this) { private val getTransitionMethod = classOf[com.sun.javafx.scene.control.skin.TitledPaneSkin].getDeclaredMethod("getTransition") getTransitionMethod.setAccessible(true) override protected def computePrefHeight(width: Double) = { val contentContainer = getChildren().get(0) val titleRegion = getChildren().get(1) val headerHeight = Math.max(com.sun.javafx.scene.control.skin.TitledPaneSkin.MIN_HEADER_HEIGHT, snapSize(titleRegion.prefHeight(-1))); var contentHeight = 0.0; if (getSkinnable().getParent() != null &amp;&amp; getSkinnable().getParent().isInstanceOf[com.sun.javafx.scene.control.skin.AccordionSkin]) { contentHeight = contentContainer.prefHeight(width); } else { contentHeight = contentContainer.prefHeight(width) * getTransitionMethod.invoke(this).asInstanceOf[java.lang.Double].toDouble } headerHeight + snapSize(contentHeight) + snapSpace(getInsets().getTop()) + snapSpace(getInsets().getBottom()); } }) } </code></pre> <p>This works for my use case, but there are some limitations, some of which can be worked around, and some that cannot.</p> <ul> <li>This code is brittle, as it depends on specific implementation details of Java FX, especially the part where I have to call a private method on TitlePane's default skin. I don't see any easy way to fix this, other than to re-implement TitlePane's default skin in its enteritety (which I guess isn't too difficult, since the code is available).</li> <li>Clamping the minWidth of the TitlePane to 0 it potentially problematic. A more robust algorithm might be necessary, depending on the use case.</li> <li>Similarly, hard-coding title pane's content bias to HORIZONTAL isn't ideal. A more robust solution would be to use the content bias of its content, and make the dimension calculations of the control work based on that content bias.</li> </ul> <p>Despite the limitations, this code seems to work for me, and I think the modifications to make it more robust are fairly straightforward. However, if anyone has a less drastic solution, or can improve on mine, please contribute.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload