JavaFX:如何检测 TitledPane 中的渲染结束?

JavaFX: How can I detect end of rendering in TitledPane?

这是我提问的背景:

我有一个带有手风琴的 GUI,其中包含许多 TitledPanes,并且每个 Titledpane 都包含一个来自 controlsFX 包的电子表格视图。 代码中有一个搜索功能,其中打开一个 Titledpane 并打开 spreadsheetView 中的特定单元格以使用 spreadsheetcell 类型的编辑方法进行文本输入。

如果 TitledPane 已经打开,这可以正常工作,但如果它必须先打开,那么编辑方法的调用就会失败。 (该程序实际上是用 scalafx 编写的,但我认为这在这里并不重要,因为 scalafx 只是 javaFX 的包装器并调用所有 javaFX 方法。) scalafx 用户组的某人发现,当我输入 350 毫秒的等待时间(TitledPane 的动画时间为 300 毫秒)时,单元格上的 'edit' 调用成功。当TitledPane 的内容呈现不完整时,他认为调用失败。 当我关闭 TitledPane 的动画时也是如此。在这种情况下,等待50ms就足够了,这在动画打开时不起作用。

无论如何 - 我担心只是等待 350 毫秒并希望这将始终有效。这让我回到了这个问题:我如何判断 TitledPane(或 spreadsheetView?)内的渲染已完成,以便我可以安全地调用 spreadsheetView 上的编辑方法?

令人惊讶的是,这似乎不受支持。

在 expand/collapse 阶段发生变化的 属性 是内容的高度:所以一个 hack around 可能是听它并在完全展开时开始编辑(这本身有点 hacky ,也可能因布局限制而改变)。

下面的示例只是在显示后初始化完全展开高度,监听内容的高度属性,并在达到完全展开高度时开始编辑。

代码:

public class TitledPaneEndOfExpansion extends Application {

    private DoubleProperty expandedHeight = new SimpleDoubleProperty();
    private TitledPane titled = new TitledPane();
    private Parent createContent() {
        titled.setText("Titled");
        ListView<String> list = new ListView<>(FXCollections.observableArrayList("some", "content"));
        list.setEditable(true);
        list.setCellFactory(TextFieldListCell.forListView());
        titled.setContent(list);
        list.heightProperty().addListener((src, ov, nv) -> {
            if (nv.doubleValue() == expandedHeight.get()) {
                list.edit(0);
            }
        });
        BorderPane content = new BorderPane(titled);
        return content;
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.setTitle(FXUtils.version());
        stage.show();
        expandedHeight.set(((Region) titled.getContent()).getHeight());
    }

    public static void main(String[] args) {
        launch(args);
    }

}

基本上我喜欢 kleopatras 的想法,但不幸的是我不知道这是否适合我。
起初我在阅读代码时遇到了一些问题 - 只是因为我的 java 知识非常有限。所以我把它转移到scala。当我 运行 它在那里时,编辑调用有时只起作用(启动后它不起作用,当我点击一个单元格进行编辑时它起作用)。所以我添加了一个也调用编辑的按钮 - 它具有相同的行为。所以一般调用编辑似乎在 scalafx 中有问题。但我在这里学到了一些有趣的东西。我现在将再等几天,看看是否有人能想到其他任何东西。如果没有,那么我将接受 kleopatras 解决方案。

为了我自己的参考,我在这里添加了我不工作的 scala 代码:

import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.beans.property.DoubleProperty
import scalafx.beans.value.ObservableValue
import scalafx.collections.ObservableBuffer
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.cell.TextFieldListCell
import scalafx.scene.control.{Button, ListView, TitledPane}
import scalafx.scene.layout.BorderPane

object TitledPaneEndOfExpansion extends JFXApp {
  val expandedHeight = new DoubleProperty()
  val data: ObservableBuffer[String] = new ObservableBuffer[String]() ++= List("some", "content", "for", "testing")

  stage = new JFXApp.PrimaryStage {
    title = "JavaFX: edit after rendering test"

    val list: ListView[String] = new ListView[String](data) {
      editable = true
      cellFactory = TextFieldListCell.forListView()
      height.onChange { (source: ObservableValue[Double, Number], oldValue: Number, newValue: Number) =>
        println("old height is: " + oldValue.doubleValue() + "   new height is: " + newValue.doubleValue())
        if (newValue.doubleValue() == expandedHeight.value) {
          edit(1)
        }
      }
    }

    val titled: TitledPane = new TitledPane {
      text = "titled"
      content = list
    }

    scene = new Scene {
      root = new BorderPane {
        center = titled
        bottom = new Button() {
          text = "edit cell 1"
          onAction = { _: ActionEvent => list.edit(1) }
        }
      }
    }
    expandedHeight.value = 400
    list.edit(1)
  }
}