Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 在VBox中的标题窗格中换行文字_Scala_Javafx_Javafx 2 - Fatal编程技术网

Scala 在VBox中的标题窗格中换行文字

Scala 在VBox中的标题窗格中换行文字,scala,javafx,javafx-2,Scala,Javafx,Javafx 2,我有包含大量文本的标题窗格。标题窗格放在VBox中,用于垂直布局。但是,当放置在VBox中时,标题栏的宽度将变为文本的全宽,而不是环绕文本。如何使标题栏的宽度为可用区域的宽度,如有必要,将其内容包裹起来 在本例中,文本换行按预期工作,但没有VBox,因此不能有多个标题窗格 package nimrandsLibrary.fantasyCraft.characterBuilder import javafx.scene.control._ import javafx.scene.layout._

我有包含大量文本的标题窗格。标题窗格放在VBox中,用于垂直布局。但是,当放置在VBox中时,标题栏的宽度将变为文本的全宽,而不是环绕文本。如何使标题栏的宽度为可用区域的宽度,如有必要,将其内容包裹起来

在本例中,文本换行按预期工作,但没有VBox,因此不能有多个标题窗格

package nimrandsLibrary.fantasyCraft.characterBuilder

import javafx.scene.control._
import javafx.scene.layout._
import javafx.scene._

class TiltedTextExample extends javafx.application.Application {
  def start(stage : javafx.stage.Stage) {
    val titledPane = new TitledPane()
    titledPane.setText("Expand me!")
    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)
    stage.setScene(new Scene(titledPane, 300, 300))
    stage.show()
  }
}

object TiltedTextExample extends App {
  javafx.application.Application.launch(classOf[TiltedTextExample])
}
在本例中,标题窗格放置在VBox中,以便可以添加多个标题窗格并垂直堆叠。令人费解的是,这打破了单词包装行为

package nimrandsLibrary.fantasyCraft.characterBuilder

import javafx.scene.control._
import javafx.scene.layout._
import javafx.scene._

class TiltedTextExample extends javafx.application.Application {
  def start(stage : javafx.stage.Stage) {
    val titledPane = new TitledPane()
    titledPane.setText("Expand me!")
    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)
    val vBox = new VBox()
    vBox.getChildren().add(titledPane)
    stage.setScene(new Scene(vBox, 300, 300))
    stage.show()
  }
}

object TiltedTextExample extends App {
  javafx.application.Application.launch(classOf[TiltedTextExample])
}

使用文本而不是标签。示例如下:

  @Override
  public void start(Stage primaryStage) {
    StackPane root = new StackPane();

    primaryStage.setScene(new Scene(root, 300, 250));

    primaryStage.setTitle("Hello World!");

    VBox vBox = new VBox();
    TitledPane tPane = new TitledPane();
    tPane.setText("expand me");
    tPane.setPrefWidth(root.getWidth());

    Text text = new Text();
    text.setText("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.");
    text.setWrappingWidth(tPane.getPrefWidth());

    tPane.setContent(text);

    vBox.getChildren().add(tPane);

    root.getChildren().add(vBox);

    primaryStage.show();
}
javafx的标题栏将占据其子项的最大宽度

结果:

我必须深入研究(查看JavaFX代码本身),但我找到了一个可行但不理想的解决方案

问题基本上归结为这样一个事实:标题窗格的编码不支持水平内容偏差(其最小/首选高度是根据其可用宽度计算的)。因此,即使它的内容标签支持此功能,它的标题窗格也会显示它的最小尺寸和首选尺寸,而不考虑其他尺寸,在这种情况下,标签控件只要求在一行上显示所有文本所需的宽度和高度

为了克服这种行为,我必须重写三个函数,两个在标题窗格本身中,一个在标题窗格的默认外观中(它实际上为标题窗格进行尺寸计算)。首先,我重写getContentBias返回值。然后,我重写getMinWidth以返回0。最后,我更新了skin的computePrefHeight函数,以在询问孩子需要多少高度时考虑可用宽度

代码如下:

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 && 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());
    }
  })
}
这适用于我的用例,但也有一些限制,其中一些可以解决,一些不能解决

  • 这段代码很脆弱,因为它取决于JavaFX的具体实现细节,特别是我必须在TitlePane的默认外观上调用私有方法的部分。除了在其Enterty中重新实现TitlePane的默认外观(我想这并不太难,因为代码是可用的),我没有看到任何简单的方法来解决这个问题
  • 将标题栏的最小宽度钳制为0可能会有问题。根据用例的不同,可能需要一个更健壮的算法
  • 类似地,硬编码标题窗格的内容偏向于水平也不理想。更可靠的解决方案是使用其内容的内容偏差,并根据该内容偏差进行控制的维度计算

尽管有这些限制,但这段代码似乎适合我,我认为使其更健壮的修改相当简单。但是,如果有人有一个不太激烈的解决方案,或者可以改进我的,请提供。

在您的示例中,您硬编码了宽度。这对我的用例不起作用,因为我需要在运行时将文本包装在可用空间内。如果标题窗格直接放在根场景对象中,而不是放在VBox中,则可以精确地执行此操作。@Nimrand您可以获取父组件的宽度(例如场景),并将其设置为文本组件的SetWrappingText()。用修改过的代码更新了我的答案。我感谢你的帮助,但我真的需要一个通用的解决方案。此示例仅在VBox位于窗口的根位置或控件宽度未动态确定的布局中有效。但是,我需要一些无论控件放在UI中的什么位置都能工作的东西,而不需要手动编码来容纳特定类型的父布局控件(例如,拆分窗格)。