gpt4 book ai didi

javafx - Gluon ScrollPane 刷新问题

转载 作者:行者123 更新时间:2023-12-03 21:28:09 25 4
gpt4 key购买 nike

我有一个在 Android 中运行的消息应用程序,其设置类似于 setup of the screen
顺序如下

<View>
<BorderPane>
<center>
<ScrollPane>
<content>
<VBox> //issue is here
</content>
<ScrollPane>
<center>
<bottom>
<TextField>
<bottom>
</BorderPane>
</View>

当我将 child 添加到 VBox 时
VBox.getChildren().add(TextLabel);

ScrollPane 获取新的 VBox 并将其显示在屏幕上。
但是,当我添加更多当前屏幕可以容纳的 child 时,我通过设置 vvalueProperty(); 滚动到 ScrollPane 的末尾;
ScrollPane.vvalueProperty().bind(VBox.heightProperty());

(以上代码对于重现问题至关重要)

这在计算机上运行时效果很好,但在移动设备上我有一个奇怪的问题,当我添加的 child 数量超过屏幕上可以容纳的数量时,scrollPane 会丢弃 VBox。当我单击 VBox 区域时,屏幕会刷新,我会在屏幕上获得所需的内容
Video demonstrating ScrollBar issue in gluon

为方便起见,我设置了以下颜色代码

滚动条 - 红色

VBox - 蓝色

作为绑定(bind)的替代方法,我也尝试过
 ScrollBar.setVvalue(1.0);

setVvalue() 没有同样的问题,但另一方面,这并没有显示 View 中的最后一条消息。
现在我已经尝试了所有可能的组合,包括用 FlowPane 替换 VBox 并观察到相同的行为。

最佳答案

我可以在 Android 设备上重现您的问题。不知何故,正如上面评论中所讨论的,垂直滚动位置的绑定(bind)导致了一些竞争条件。

与其试图找出导致该问题的原因,我宁愿删除绑定(bind)并提出一种不同的方法来获得所需的结果:在这种情况下,绑定(bind)是一个非常强的条件。

当您尝试在同一 channel 中执行此操作时:

vBox.getChildren().add(label);
scrollPane.setVvalue(vBox.getHeight());

您已经注意到并提到滚动位置没有正确更新,并且您错过了添加到 vBox 的最后一项。

这很容易解释:当您将新项目添加到框中时,会调用 layoutChildren()这将需要一些时间来执行。至少需要另一个脉冲才能获得正确的值。

但是由于您尝试立即设置垂直滚动位置,因此值 vBox.getHeight()仍将返回旧值。换句话说,您必须稍等片刻才能获得新值。

有几种方法可以做到这一点。最直接的方法是收听盒子的 height。属性(property):
vBox.heightProperty().addListener((obs, ov, nv) -> 
scrollPane.setVvalue(nv.doubleValue()));

作为替代方案,在将项目添加到框中后,您可以使用:
vBox.getChildren().add(label);
Platform.runLater(() -> scrollPane.setVvalue(vBox.getHeight()));

但这并不能保证调用不会立即完成。所以最好做一个 PauseTransition相反,您可以在其中控制时间:
vBox.getChildren().add(label);

PauseTransition pause = new PauseTransition(Duration.millis(30));
pause.setOnFinished(f -> scrollPane.setVvalue(vBox.getHeight()));
pause.play();

作为建议,您还可以做一个很好的过渡以滑入新项目。

替代解决方案

到目前为止,您使用的是 ScrollPane结合 VBox添加多个项目,允许滚动到列表中的第一个项目,但滚动位置始终位于底部,因此添加的最后一个项目完全可见。虽然这很好用(上面我的建议是避免绑定(bind)),但您正在将许多节点添加到非虚拟化容器中。

我认为有一个更好的选择, ListView (或者更好的 CharmListView 将允许标题)。使用正确的 CellFactory您可以拥有完全相同的视觉效果,并且可以直接滚动到最后一项。但是这个控件的主要优点是它的 virtualFlow,它将为您管理有限数量的节点,同时您可以将更多项目添加到列表中。

这只是一个使用 ListView 的简短代码片段。控制您的聊天应用程序:
ListView<String> listView = new ListView<>();
listView.setCellFactory(p -> new ListCell<String>() {
private final Label label;
{
label = new Label(null, MaterialDesignIcon.CHAT_BUBBLE.graphic());
label.setMaxWidth(Double.MAX_VALUE);
label.setPrefWidth(this.getWidth() - 60);
label.setPrefHeight(30);
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null && ! empty) {
label.setText(item);
label.setAlignment(getIndex() % 2 == 0 ? Pos.CENTER_LEFT : Pos.CENTER_RIGHT);
setGraphic(label);
} else {
setGraphic(null);
}
}

});
setCenter(listView);

并添加一个新项目并滚动到它,您只需要:
listView.getItems().add("Text " + (listView.getItems().size() + 1));
listView.scrollTo(listView.getItems().size() - 1);



当然,通过适当的样式,您可以删除行之间的线条,并创建与使用 scrollPane 相同的视觉效果。

关于javafx - Gluon ScrollPane 刷新问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50918779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com