【问题标题】:Customizing existing controls in JavaFX (JDK 8)在 JavaFX (JDK 8) 中自定义现有控件
【发布时间】:2014-03-04 20:43:55
【问题描述】:

关于

早上好,Stackoverflow 社区。我(再次)搬到这里是为了给我们的思维带来一些混乱。我目前正在研究JavaFX控件的定制和创建。在创建自己的控件方面取得了巨大成功,并且对结果非常满意。然而,当我开始尝试自定义现有的 JavaFX 控件时,事情开始变得复杂。

问题

我们知道 Oracle 包中的控件非常高效,但不幸的是,它们对我来说很无聊。我尝试修改它们的外观,为此,我开始使用 CSS 样式,这很容易做到。我得到了预期的外观,但事情似乎仍然很无聊。

控件似乎突然改变了它们的状态,没有动画,没有状态转换的效果,什么都没有。当我尝试开始添加一些动画时,我意识到有些控件是由不同的组件组成的。

我们以 ScrollBar 控件为例。 ScrollBar 由两个按钮组成,thumb、track 和 trackbackground。这些组件被认为是子结构as mentioned in JavaFX CSS own documentation(在“javafx.scene.control”主题中也提到过),并且可以使用大于字符 (>) 轻松访问。即使可以访问这些类型的 CSS 样式子结构,我在尝试用纯 Java 代码访问它们时也遇到了问题。

我出于什么原因尝试访问这些组件?好吧,我想控制情况,以便能够为某些特定情况制作动画并添加更多组件。想象一下,我有以下风格化的滚动条:

IMAGE

MIRROR 1 & MIRROR 2

我希望我可以为这个滚动条上的一些组件设置动画。我希望当用户单击箭头时,它们会以动画形式移动。同样,当鼠标悬停在箭头和拇指上时,它们会启动模糊效果,但又快又轻。

让我感到困惑的一个奇怪案例是当我尝试对 Button 进行风格化时。我可以通过 CSS 设置 Button 类的样式,但是对于 Button 中的现有文本,我什至无法通过 CSS 对其应用效果。在我看来,Button 内部存在文本子结构,因此无法应用 CSS 效果。

可能的解决方案

为了实现这一目标,我最终找到了 AquaFX 及其源代码。发现 AquaFX 开发人员似乎使用了来自 Parent 类的名为“lookup”的方法,试图在 Java 代码中查找皮肤的现有子结构。现有皮肤的许多子结构都是 StackPane 类型,我真的不明白。在尝试获取此类引用时,我遇到了以下代码 sn-p(例如,对于 ScrollBarSkin 子类型):

StackPane thumb = (StackPane) super.getSkinnable().lookup(".thumb");

事实上,例如,我能够获得对 ScrollBar 子结构的引用,但仍有一些事情困扰着我。

最后的问题

即使我已经找到了获取子结构引用的方法,正如我之前提到的,我仍然有一些问题(或者我在社区中提出问题对我来说没有意义):

  1. 出于什么原因我无法访问现有的子结构文本 按钮(如果存在)?
  2. 为什么大多数(如果不是全部)现有子结构都是 StackPane?
  3. 使用 Parent 的方法查找确实是一种正确(或最佳、或理想)的方式 对控件的外观进行一些更改并添加一些 动画?

注意:这里的一些用户可能最终会发现在社区中创建的一个新问题中放置 3 个问题是不必要的。但是,这 3 个问题都涉及同一个主题,即现有控件的正确自定义。

我在这里并不是说 AquaFX 开发人员不称职。没门!我对编辑和自定义现有控件这一主题不熟悉,因此我试图更多地了解它。我在互联网上几乎没有找到任何让我有信心的学习资料,而且我知道在这里我们有一个完整的专业知识社区可以帮助我们(这里甚至有在 Oracle 工作的人,或者那里有朋友) .

【问题讨论】:

    标签: java css javafx javafx-8 skin


    【解决方案1】:

    1.为什么我无法访问现有的子结构文本按钮(如果存在)?

    因为按钮本身就是一个“文本”。 Button 扩展 ButtonBase 并且那个扩展 Labeled。阅读相关的 javadocs 以获取更多信息。要操作文本属性,请使用 -fx-text-* css 选择器。但是要为按钮的文本设置动画,正确的方法是设置按钮的图形节点,并为该图形节点设置动画。

    2.大多数(如果不是全部)现有子结构是 StackPane 的原因是什么?

    IMO,由于 StackPane 自动将其子级堆栈与对齐 Pos.CENTER 自动放置在后到前堆栈,这在大多数用例中都是合适的。

    3.使用 Parent 的方法查找,真的是对控件的外观进行一些更改并添加一些动画的正确(或最佳、或理想)方法吗?

    这是从父容器中获取子容器的首选方式(即 api 方式)。如果您要实施自己的方法,最终可能会得到相同的解决方案。因此,您只能获取孩子一次,并在进一步使用时继续参考它。
    lookup() 方法在 Node 中实现,并在 Parent (JavaFX 2.2) 中被覆盖。用法见Usage of lookup。查找方法使用方法Selector.createSelector()。通过调查这些源代码(有点旧的版本),可以做一些结论。如果您有改进建议或发现错误,可以将它们提交到 jira 问题跟踪器。

    但是,如果您知道父节点的图结构,您当然可以执行child = parent.getChildren().get(4).getChildren().get(12); 之类的操作。

    【讨论】:

    • 嗯 .. 真的这一切都说得通!谢谢!关于我的第三个问题的答案,您至少对此主题有一些参考吗?在某些 JavaFX API 类的源代码中是否存在对方法查找的调用?你能告诉我让我看看吗?我也会搜索。
    • 谢谢!我现在感觉更有信心了。你真的帮了我很多! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 2016-06-28
    • 2014-10-10
    • 1970-01-01
    相关资源
    最近更新 更多