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

选择条

最近,我不得不实现一个自定义控件,该控件使用户可以从项目列表中选择一个项目。 此“ 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/345367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通信中的频谱效率与能量效率

频谱效率(Spectral Efficiency) 频谱效率&#xff08;Spectral Efficiency&#xff0c;SE&#xff09;简称谱效&#xff0c;也称系统容量、频带利用率。 该指标用来衡量系统的有效性&#xff0c;描述了能够提供多少容量。 它定义为系统传输的有效信息速率R除以通信信道带宽B&a…

积分公式大全

https://kexue.fm/sci/integral/ 《积分公式大全》网络版本——By BoJone 引用原作者的话&#xff1a; 本附件所有公式来自《高等数学第三版》。   该书信息&#xff1a;同济大学数学教研室编&#xff0c;高等教育出版社&#xff0c;1988年4月第三版&#xff0c;ISBN 7-04-0…

Latex快速入门系列 -- 在TexStudio中正确插入参考文献的基本操作

目录 1 操作流程2 四种基本的文献格式比较3 文献数据库.bib的编写 1. 操作流程 1.1 创建文章主文件。Ctrl N 新建一个文件&#xff0c;Ctrl S 手动保存&#xff0c;保持文件后缀名.tex。得到一个.tex文件&#xff1a;文章名.tex&#xff0c;该文件用来编写你的文章的具体内…

MongoDB索引策略和索引类型

1. MongoDB索引策略和索引类型–简介 MongoDB是一个开放源代码&#xff0c;面向文档的跨平台数据库&#xff0c;它使用C 开发&#xff0c;并且是最流行和使用最广泛的NoSQL类型数据库之一。 它可在具有键-值对的类JSON文档的顶部运行&#xff0c;其键值对在每个文档中都无法定义…

zeal刷新不出来_推进重涂市场标准化,立邦率先推出刷新服务“八大验收标准”...

点击蓝字【立邦中国】&#xff0c;设置星标关注。7月&#xff0c;立邦刷新服务率先在墙面重涂行业提出突破性的“八大验收标准”&#xff0c;根据不同的涂刷工艺来采用定制化的验收标准&#xff0c;更进一步推动重涂市场的标准化和规范化。自2011年推出立邦刷新服务至今&#x…

初学者指南:如何为Red Hat Process Automation Manager配置电子邮件服务任务

最近&#xff0c;我一直在更新我的免费在线研讨会 &#xff0c;特别是基于JBoss BPM Suite的系列研讨会 &#xff0c;以便您可以开始使用较新的Red Hat Process Automation Manager 。 在本文中&#xff0c;我将分享我在自动化项目中尝试使用电子邮件通知时偶然发现的内容。 …

TDMA 时分多路复用

多路复用 一、什么是多路复用技术&#xff1f; 多路复用技术是把若干个低速信道组成一个高速信道的技术&#xff0c;可以提高数据链路利用率&#xff0c;从而使一条高速的主干链路同时为多条低速的接入链路提供服务&#xff0c;即使网络主干链路可同时运载大量的语音和数据传…

asp 取数据 计算_ASP.NET Core 简介

.NET Core 是 .NET Framework 的新一代版本&#xff0c;是微软开发的第一个具有跨平台 ( Windows、Mac OSX 、Linux ) 能力的应用程序开发框http://ASP.NET Core 是 Microsoft 新开发的&#xff0c;基于 .NET Core 的 Web 开发框架http://ASP.NET Core 是对 http://ASP.NET 的重…

java字节码_掌握Java字节码

java字节码嘿! Happy Advent&#xff1a;D我是ZeroTurnaround的技术布道者Simon Maple&#xff08; sjmaple&#xff09; 。 您知道&#xff0c; JRebel伙计们&#xff01; 由于编写了类似JRebel的产品&#xff0c;该产品与字节码进行交互的结果比您想像中的要多&#xff0c;因…

自由空间激光通信

一、空间激光通信系统 空间激光通信系统是指以激光光波作为载波&#xff0c;大气作为传输介质的光通信系统。自由空间激光通信结合了光纤通信与微波通信的优点&#xff0c;既具有大通信容量、高速传输的优点&#xff0c;又不需要铺设光纤&#xff0c;因此各技术强国在空间激光…

icom对讲机写频线定义_小米对讲机Lite体验:小米全新5公里无网络免费通话神器...

沟通&#xff0c;或者可以简单地把它说成是一种信息的传递。它对于世间的生灵来说&#xff0c;都很重要&#xff01;尤其是对于人类&#xff0c;更为重要&#xff01;由古至今&#xff0c;人们为了可以更好地进行信息的传递&#xff0c;想出了各种各样的办法&#xff0c;比如古…

Spring Boot应用程序的“本地服务”

我有机会尝试使用Knative的 Serving功能来部署Spring Boot应用程序&#xff0c;而这篇文章只是记录了示例和我采用的方法。 我对Knative的内部知识还不够了解&#xff0c;无法就此方法是否比基于部署 服务 基于入口的方法更好。 一项很棒的功能是Knative Serving中的自动缩放…

一文读懂:常见低通、高通、带通三种滤波器的工作原理

滤波器 滤波器是对波进行过滤的器件&#xff0c;是一种让某一频带内信号通过&#xff0c;同时又阻止这一频带外信号通过的电路。 滤波器主要有低通滤波器、高通滤波器和带通滤波器三种&#xff0c;按照电路工作原理又可分为无源和有源滤波器两大类。今天&#xff0c;小编主要…

红米ac2100breed看模块_骁龙865加持,红米K30S至尊纪念版11日再开售

红米K30S至尊纪念版在11月1日首销&#xff0c;仅用了1分钟便售出10万台&#xff0c;热度颇高。11月11日0点&#xff0c;红米K30S至尊纪念版将再度开售&#xff0c;售价2299元起。以2299元起步的价格&#xff0c;红米K30S至尊纪念版配备了高通骁龙865处理器&#xff0c;8GB LPDD…

常用求和公式和级数

1. 多项式级数 2. 指数级数 3. Harmonic 级数 4. 其他 常见的级数查询表 https://blog.csdn.net/algzjh/article/details/82533996 https://www.zhihu.com/topic/19998598/hot

个盘子的汉诺塔需要移动几步_看漫画学C++039:递归解汉诺塔

点击蓝字 关注我们本话内容请输入相传在古印度圣庙中&#xff0c;有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上&#xff0c;有三根杆(编号A、B、C)&#xff0c;在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标&#xff1a;把A杆上的金盘全部移到…

八位图 16位图_了解位图

八位图 16位图几周前&#xff0c;我和Alistair正在研究用于对节点附加到Neo4j数据库中的标签进行建模的代码。 这种工作方式是将32个节点ID的块表示为每个标签的32位位图 &#xff0c;其中1表示1表示节点具有标签&#xff0c;0表示没有标签。 例如&#xff0c;假设我们有节点…

调制深度,峰均值功率比,脉冲整形等因素对于调制损耗的影响...

我们知道光发射机中一个非常重要的参数是发射功率。如果光发射机处于无源光网络&#xff08;PON&#xff09;&#xff0c;没有后续放大器的情况&#xff0c;发射功率很大程度上决定了发射机可以传输的距离 &#xff08;功率预算&#xff0c;power budget&#xff09;&#xff1…

移动流量转赠给好友_私域流量的五大认知误区

各大品牌主对于私域流量存在的认知误区 &#xff0c;你是否也这样认为&#xff1f;目前看起来&#xff0c;私域流量好像只要前期投入&#xff0c;后期就可以为自身带来源源不断的流量&#xff0c;但是私域流量真的像看起来那么美吗&#xff1f;其实不是的&#xff0c;我们对于私…

MATLAB 显示输出数据的三种方式

1. 改变数据格式 当数据重复再命令行窗口时&#xff0c;整数以整形形式显示&#xff0c;其他值将以默认格式显示。MATLAB的默认格式是精确到小数点后4位。如果一个数太大或太小&#xff0c;那么将会以科学记数法的形式显示。比如&#xff1a; >> x100.11x 100.1100>…