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

问题描述

这是我问题的背景:

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

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

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

解决方法

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

在展开/折叠阶段改变的属性是内容的高度:所以一个hack可能是听它并在完全展开时开始编辑(这本身有点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 中调用 edit 似乎有问题。但我在这里学到了一些有趣的东西。我现在再等几天,看看有没有人能想到别的。如果没有,那么我将接受 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)
  }
}