【问题标题】:Weird ScrollBar behavior when bound to ScrollPane ScrollBar绑定到 ScrollPane ScrollBar 时出现奇怪的 ScrollBar 行为
【发布时间】:2018-05-23 14:47:19
【问题描述】:

我已经构建了一个控件,它为 JavaFX 提供类似于 Twitter Bootstrap 导航栏的行为。它基本上由背面带有 ScrollPane 的 StackPane、顶部带有顶部、底部条的 BorderPane 以及最顶层右侧带有 ScrollBar 的 BorderPane 组成。 这应该支持以下场景:

  • 在顶部和底部有固定的元素,滚动时不会移动(à la navbar)
  • 拥有一个位于内容顶部的 ScrollBar,这与 ScrollPanes 的默认行为不同,它将内容推送到左侧以便为内置 ScrollBar 提供空间

因此 StackPane 布局。

布局部分工作正常,做我想要的。不过,我的 ScrollBar 的行为很奇怪。当内容可滚动时,本机 ScrollBar(由 ScrollPane 管理的)如下所示:

红线表示拇指可能具有的最大尺寸的估计值。因此,对于可滚动的内容,ScrollBar 不是尽可能高,这是正确的。

现在我的实现对可滚动内容的行为有所不同。我可以观察到两种行为:

ScrollBar 拇指很小,尽管本机拇指具有正确的大小。或者:

即使内容是可滚动的,拇指也有最大尺寸。 在滚动工作时,这两个示例在视觉效果方面显然是错误的。 我绑定两个 ScrollBars 属性的代码如下所示:

vScrollBar.valueProperty().bindBidirectional(scrollPane.vvalueProperty());
vScrollBar.maxProperty().bind(scrollPane.vmaxProperty());
vScrollBar.minProperty().bind(scrollPane.vminProperty());
nodeListChangeListener = c -> {
    ScrollBar hiddenScrollBar = getScrollBarFromScrollPane(scrollPane, Orientation.VERTICAL);
    if (hiddenScrollBar != null) {
        vScrollBar.visibleAmountProperty().bind(hiddenScrollBar.visibleAmountProperty());
        vScrollBar.blockIncrementProperty().bind(hiddenScrollBar.blockIncrementProperty());
        vScrollBar.unitIncrementProperty().bind(hiddenScrollBar.unitIncrementProperty());
        scrollPane.getChildrenUnmodifiable().removeListener(nodeListChangeListener);
    }
};
scrollPane.getChildrenUnmodifiable().addListener(nodeListChangeListener);

另一件值得一提的是,在我使用此控件的几乎所有其他地方,它的行为都是正确的。只有少数几个地方会发生这种情况,但我不明白它是怎么可能的。


最后:我在这里缺少什么属性?考虑到我将所有这些属性从 ScrollPane ScrollBar 绑定到我的自定义覆盖 ScrollBar (vScrollBar),这两个 ScrollBar 的行为是否应该相同?

【问题讨论】:

  • 能否请您添加 minimal reproducible example 您如何创建组件以及 getScrollBarFromScrollPane() 的作用。还要验证 hiddenScrollBar 不是 null

标签: java javafx javafx-8


【解决方案1】:

(我假设getScrollBarFromScrollPane(scrollPane, Orientation.VERTICAL); 调用(ScrollBar)scrollPane.queryAccessibleAttribute(AccessibleAttribute.VERTICAL_SCROLLBAR);

我不知道你是如何创建组件的,但很可能hiddenScrollBar 只是null 并且可见的 ScrollBar 永远不会绑定到 ScrollPane 的 ScrollBar。

发生这种情况是因为nodeListChangeListener 在创建ScrollPaneSkin 期间但在属性skin 设置之前被通知,因此无法访问滚动条。

要正确绑定滚动条,您可以将侦听器添加到skinProperty

scrollPane.skinProperty().addListener(c -> {
    ScrollBar hiddenScrollBar = (ScrollBar)scrollPane.queryAccessibleAttribute(AccessibleAttribute.VERTICAL_SCROLLBAR);
    if (hiddenScrollBar != null) {
        bar.visibleAmountProperty().bind(hiddenScrollBar.visibleAmountProperty());
        bar.blockIncrementProperty().bind(hiddenScrollBar.blockIncrementProperty());
        bar.unitIncrementProperty().bind(hiddenScrollBar.unitIncrementProperty());
    }
});

【讨论】:

  • 抱歉回复晚了,今天才可以访问代码。这成功了,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-29
  • 2012-03-16
  • 1970-01-01
  • 2015-05-10
  • 2022-10-01
相关资源
最近更新 更多