javafx 遮罩

选择条

最近,我不得不实现一个自定义控件,该控件使用户可以从项目列表中选择一个项目。 此“ SelectionStrip”控件必须水平放置项目,并且在项目过多的情况下,允许用户左右水平滚动。 该控件将在空间受限的区域中使用,因此用于滚动的按钮应仅在需要时显示。 显示时,它们也不应浪费任何额外的空间。 因此,我决定将它们放置在控件左侧和右侧的顶部。 所有这些都很容易实现,除了现在很难将滚动按钮与项目区分开。 可以在下面的三个图像中看到。

阿尔法频道?

因此,我认为在靠近左侧或右侧边缘时以某种方式淡出项目会很好。 这种行为通常可以通过使用alpha通道来完成。 随着像素到边缘的距离减小,可能会降低像素的不透明度。 好的.....但是在JavaFX中如何完成呢? 在相当长的一段时间里,我一直在研究各种“混合模式”,这些模式可以用来定义两个重叠节点如何在彼此之上绘制。 但是,这是错误的方向。 事实证明,我已经知道该怎么做,因为我曾经写过一篇博客文章,内容涉及剪辑以及填充和未填充剪辑之间的区别 。 但是我想这是很久以前的事了,我没有在“填充”和“不透明度小于1”之间建立联系。

复杂剪辑!

到目前为止,我用于自定义控件的大多数剪辑都是简单的矩形。 他们通常确保到达其父控件的布局范围之外的子节点不可见或仅部分可见。 但是此剪辑不同,它更加复杂。 它必须定义三个不同的区域。 左侧为“淡入”区域,中间为“完全不透明”区域,右侧为“淡出”区域。 为此,我定义了一个“组”,它由三个填充的“矩形”节点组成。 中心矩形的填充颜色为纯黑色,而其他两个矩形的填充颜色为从透明到黑色的线性渐变,反之亦然。 下图说明了这一点。

通过此设置,我们现在可以将任何节点作为子节点添加到堆栈窗格中,并且将在其侧面用淡入和淡出效果进行绘制。

结果

从一开始就将滚动箭头/按钮应用于“ SelectionStrip”控件后,它现在始终清晰可见,并且整体用户体验变得更加令人愉悦。 这些小细节使被认为是“学生项目”或“商业应用程序”的UI有所不同。 因此有时值得在这些上投入时间。

源代码

我将屏蔽逻辑放入了一个称为“ MaskedView”的自定义控件中。 在本文的底部,您将看到包含此​​控件源代码的Gist(或Gist链接)。 可以将其视为给定内容节点的包装器。

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Node;
import javafx.scene.control.Control;
import javafx.scene.control.Skin;public class MaskedView extends Control {public MaskedView(Node content) {setContent(content);}@Overrideprotected Skin<?> createDefaultSkin() {return new MaskedViewSkin(this);}private final SimpleObjectProperty<Node> content = new SimpleObjectProperty<>(this, "content");public final Node getContent() {return content.get();}public final SimpleObjectProperty<Node> contentProperty() {return content;}public final void setContent(Node content) {this.content.set(content);}private final DoubleProperty fadingSize = new SimpleDoubleProperty(this, "fadingSize", 120);public final double getFadingSize() {return fadingSize.get();}public final DoubleProperty fadingSizeProperty() {return fadingSize;}public final void setFadingSize(double fadingSize) {this.fadingSize.set(fadingSize);}
}
import javafx.beans.InvalidationListener;
import javafx.beans.WeakInvalidationListener;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.SkinBase;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Rectangle;public class MaskedViewSkin extends SkinBase {private final Rectangle leftClip;private final Rectangle rightClip;private final Rectangle centerClip;private final Group group;private final StackPane stackPane;public MaskedViewSkin(MaskedView view) {super(view);leftClip = new Rectangle();rightClip = new Rectangle();centerClip = new Rectangle();centerClip.setFill(Color.BLACK);leftClip.setManaged(false);centerClip.setManaged(false);rightClip.setManaged(false);group = new Group(leftClip, centerClip, rightClip);stackPane = new StackPane();stackPane.setManaged(false);stackPane.setClip(group);getChildren().add(stackPane);view.contentProperty().addListener((observable, oldContent, newContent) -> buildView(oldContent, newContent));buildView(null, view.getContent());view.widthProperty().addListener(it -> updateClip());view.fadingSizeProperty().addListener(it -> updateClip());}private final InvalidationListener translateXListener = it -> updateClip();private final WeakInvalidationListener weakTranslateXListener = new WeakInvalidationListener(translateXListener);private void buildView(Node oldContent, Node newContent) {if (oldContent != null) {stackPane.getChildren().clear();oldContent.translateXProperty().removeListener(weakTranslateXListener);}if (newContent != null) {stackPane.getChildren().setAll(newContent);newContent.translateXProperty().addListener(weakTranslateXListener);}updateClip();}private void updateClip() {final MaskedView view = getSkinnable();Node content = view.getContent();if (content != null) {final double fadingSize = view.getFadingSize();if (content.getTranslateX() < 0) { leftClip.setFill(new LinearGradient(0, 0, fadingSize, 0, false, CycleMethod.NO_CYCLE, new Stop(0, Color.TRANSPARENT), new Stop(1, Color.BLACK))); } else { leftClip.setFill(Color.BLACK); } if (content.getTranslateX() + content.prefWidth(-1) > view.getWidth()) {rightClip.setFill(new LinearGradient(0, 0, fadingSize, 0, false, CycleMethod.NO_CYCLE, new Stop(0, Color.BLACK), new Stop(1, Color.TRANSPARENT)));} else {rightClip.setFill(Color.BLACK);}}view.requestLayout();}@Overrideprotected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) {final double fadingSize = Math.min(contentWidth / 2, getSkinnable().getFadingSize());stackPane.resizeRelocate(snapPosition(contentX), snapPosition(contentY), snapSpace(contentWidth), snapSpace(contentHeight));resizeRelocate(leftClip, snapPosition(contentX), snapPosition(contentY), snapSpace(fadingSize), snapSpace(contentHeight));resizeRelocate(centerClip, snapPosition(contentX + fadingSize), snapPosition(contentY), snapSpace(contentWidth - 2 * fadingSize), snapSpace(contentHeight));resizeRelocate(rightClip, snapPosition(contentX + contentWidth - fadingSize), snapPosition(contentY), snapSpace(fadingSize), snapSpace(contentHeight));}private void resizeRelocate(Rectangle rect, double x, double y, double w, double h) {rect.setLayoutX(x);rect.setLayoutY(y);rect.setWidth(w);rect.setHeight(h);}
}

希望您能找到此控件的好用例。

祝大家编码愉快!

翻译自: https://www.javacodegeeks.com/2018/07/javafx-tip-31-masking-clipping-alpha-channel.html

javafx 遮罩

javafx 遮罩_JavaFX技巧31:遮罩/剪切/ Alpha通道相关推荐

  1. JavaFX技巧31:遮罩/剪切/ Alpha通道

    选择条 最近,我不得不实现一个自定义控件,该控件使用户可以从项目列表中选择一个项目. 此" SelectionStrip"控件必须水平放置项目,并且在项目过多的情况下,允许用户左右 ...

  2. javafx 教程_JavaFX技巧6:使用透明颜色

    javafx 教程 为用户界面元素选择正确的颜色始终是一个巨大的挑战,但是当您开发可重用的框架控件时,开发人员就无法控制使用它们的应用程序的外观和感觉,这甚至更具挑战性. 尽管您可能总是将元素添加到默 ...

  3. javafx 图标_JavaFX技巧32:需要图标吗? 使用Ikonli!

    javafx 图标 动机 自2013年以来,我一直在编写JavaFX应用程序和库的代码,它们的共同点是,我需要找到可以用于它们的良好图标/图形. 作为前Swing开发人员,我首先使用图像文件,GIF或 ...

  4. javafx阴影_JavaFX技巧来节省内存! 属性和可观察对象的阴影场

    javafx阴影 在 JavaFX的世界中, Properties API允许UI开发人员将值绑定到UI控件. 这种功能出奇的简单,但是当对象模型经常使用属性时,应用程序可能会很快耗尽内存. 我通常会 ...

  5. javafx 教程_JavaFX技巧32:需要图标吗? 使用Ikonli!

    javafx 教程 动机 自2013年以来,我一直在编写JavaFX应用程序和库的代码,它们的共同点是,我需要找到可以用于它们的良好图标/图形. 作为前Swing开发人员,我首先使用图像文件,GIF或 ...

  6. javafx阴影_JavaFX技巧23:节省内存! 属性的阴影场

    javafx阴影 Java 8中引入的属性和属性绑定是非常有用的编程概念. 当您开发用户界面时,它们特别有用. 实际上,它们是如此有用,以至于开发人员成为所有事物都应该是属性而不是原始属性的想法的受害 ...

  7. javafx隐藏_JavaFX技巧14:StackPane子项-隐藏但不消失

    javafx隐藏 另一个简短提示:Swing提供了一个名为CardLayout的布局管理器,该管理器管理容器内的一组组件(卡),但始终仅显示其中一个. 方法CardLayout.show(Contai ...

  8. javafx属性_JavaFX技巧11:更新只读属性

    javafx属性 自定义控件通常具有"只读"属性. 这意味着不能从控件外部进行设置,甚至不能从自己的皮肤类别进行设置. 通常,控件的行为会导致更改只读属性. 在JavaFX中,此行 ...

  9. javafx 自定义控件_JavaFX技巧10:自定义复合控件

    javafx 自定义控件 用JavaFX编写自定义控件是一个简单直接的过程. 需要一个控件类来控制控件的状态(因此命名). 外观需要控件的外观. 而且通常不是用于自定义外观CSS文件. 控件的一种常见 ...

最新文章

  1. 数字治理转型与公共卫生治理能力现代化调查项目
  2. hdu 3395(费用流,二分图的最大权匹配)
  3. 真香!原来 CLI 开发可以这么简单
  4. fiddler和wireshark工具介绍及对比 - [测试技术知识]
  5. matlab for 取数组,for循环中的MATLAB和单元格数组处理
  6. IntelliJ IDEA 默认快捷键大全
  7. Discuz!X/缓存机制和使用方法
  8. 邢台农业计算机学校,邢台农业学校
  9. SpringBoot之Idea不显示项目文件夹
  10. flAbsPath on /var/lib/dpkg/status failed 解决 Cydia 红字
  11. Contacts Provider
  12. visio中公式太小_多元醇羟值、羟基含量与分子量之间的关系及计算公式
  13. VScode光标乱跳、换行失灵、保存导致光标乱跳等解决办法
  14. html中点击按钮闪现,vue使用v-if v-show页面闪烁,div闪现的解决方法
  15. 【毕业设计】深度学习 python opencv 实现人脸年龄性别识别
  16. 戴尔-卡耐基:《人性的弱点 How to Win Friends And Influence People》总结
  17. 超简单 不进PE 不用U盘 自己重装电脑系统步骤
  18. 【数字IC/FPGA】仲裁器进阶--Round Robin Arbiter
  19. 数据结构和算法(五)--栈(Stack)
  20. 今日头条有意向收购锤子科技;原金立总裁加入小米;苹果应用商店出现查开房记录app|雷锋早报...

热门文章

  1. 牛客题霸 [比较版本号] C++题解/答案
  2. CF662C Binary Table(FWT_XOR卷积)
  3. 数论分块练习([CF830 C]Bamboo Partition + [hdu 6395]Sequence )
  4. Loj#6053-简单的函数【Min25筛】
  5. jzoj6305-最小值【线段树,dp,双端链表】
  6. jzoj3379-查询【主席树】
  7. P3076,jzoj3187-的士【贪心】
  8. P1220-关路灯【区间dp】
  9. codeforces 932D Tree 倍增法+二分搜索
  10. Java IO: PipedOutputStream