选择条

最近,我不得不实现一个自定义控件,该控件使用户可以从项目列表中选择一个项目。 此“ 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技巧31:遮罩/剪切/ Alpha通道相关推荐

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

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

  2. php代码隐写到图片,从PNG Dropper到Alpha通道隐写术实践

    0x1 前言 前些天从安全客上看到一篇翻译文章是关于利用PNG像素隐藏PE代码,对实现细节很感兴趣就抽空稍微研究了下相关内容,于是就有了本次分享. 0x2 PNG Dropper样本分析 先来看下翻译 ...

  3. Alpha 通道的概念与功能

    RGBA         采用的颜色是RGB,可以属于任何一种RGB颜色空间,但是Catmull和Smith在1971至1972年间提出了这个不可或缺的alpha数值,使得alpha渲染和alpha合 ...

  4. JavaFX技巧6:使用透明颜色

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

  5. java图像处理-(指定区域内)灰度化、透明化(alpha通道)处理

    java图像处理-(指定区域内)灰度化.透明化(alpha通道)处理 2016年07月25日 21:23:16 阅读数:3944 近日在一家小公司实习,老板要求我写一个图形编辑器,其中涉及到用java ...

  6. [原]BMP位图 转换 透明 TGA图像 - 增加 alpha通道 -TGA文件格式初解

    最近做一个将文字转换为图片做视频叠加字幕的软件,大家都知道VB的图像控件Picture Box只能输出BMP格式位图,自然我的软件是用Picture Box做图像输出的也不例外,但是客户要求要输出带a ...

  7. OpenGL中的混色问题(Alpha通道)

    混合是一种常用的技巧,通常可以用来实现半透明.但其实它也是十分灵活的,你可以通过不同的设置得到不同的混合结果,产生一些有趣或者奇怪的图象. 混合是什么呢?混合就是把两种颜色混在一起.具体一点,就是把某 ...

  8. 亮度遮罩和alpha遮罩_在PhotoShop中将Alpha遮罩的云创建为PNG

    亮度遮罩和alpha遮罩 In previous articles we've looked at creating 32-bit PNGs for use in web pages. In this ...

  9. (4)关于Alpha通道问题

    其实,我还是不理解,我还是先把我目前懂得和觉得有用的东西先存下来 =================================================================== ...

最新文章

  1. 双屏全屏跳回到主屏_双屏双倍乐趣?华硕灵耀X2 Duo笔记本评测
  2. To handle Unhandled Exception
  3. 马来西亚国立大学的计算机,要拿到马来西亚国立大学的 offer难吗?
  4. HTML与CSS基础之属性选择器(二)
  5. python-opencv 帧差法目标检测
  6. bitset优化传递闭包
  7. 第23个520情人节,女程序猿送男朋友什么?
  8. python个税计算器代码_用python实现个税计算器
  9. PHP+经贸时间轴 毕业设计-附源码211617
  10. vue 中的 attribute 和 property
  11. k8s 1.15.1 service 的 ClusterIP模式的sessionAffinity: ClientIP 模式负载测试实验
  12. 2008-2020年各省地方债务余额数据(wind)
  13. ubuntu与win10共享LE蓝牙鼠标
  14. 有趣的CSS实现“勾号”
  15. centos 有eht2 没有eth0 无法上网
  16. Proteus仿真arduino uno + OLED图片显示
  17. Android扫描蓝牙问题,你是不是位置权限和GPS都打开了还是扫不出东西
  18. 计算机概念性的文字怎么降重,论文降重概念性的文字怎么改
  19. android StaticLayout 完美契合TextView
  20. SPSS处理单样本、多样本数据方法

热门文章

  1. 【链表】【树形DP】最大利润(jzoj 1487)
  2. JVM调优总结(2):基本垃圾回收算法
  3. 避免代码冗余,使用接口和泛型重构Java代码
  4. ssm使用全注解实现增删改查案例——EmpServiceImpl
  5. 交换数组中的两个元素
  6. python线性加权模型_局部加权之线性回归(1) - Python实现
  7. 【1】flink-source读取数据
  8. servlet设置cookie实验
  9. 关于二叉堆(优先队列)的其他操作及其应用
  10. Mybatis3(3)动态 SQL