问题描述
这是我问题的背景:
我有一个带有许多 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)
}
}