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

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 遮罩

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

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

相关文章

IntelliJ IDEA for Mac如何查看某个方法的实现

如果没有子类&#xff0c;按住 Command&#xff0c;鼠标点击方法名会跳到声明定义方法的地方&#xff1b;如果是接口或者父类&#xff0c;那么只会跳至接口或者父类声明方法的地方&#xff0c;想要看子类的实现&#xff0c;可以点击鼠标右键&#xff0c;选择 【Go To】 -> 【…

日志管理工具_您需要了解的6种日志管理工具(以及如何使用它们)

日志管理工具如果没有正确的工具来汇总和解析您的日志数据&#xff0c;则几乎不可能找到并了解所需的信息。 日志有无穷的用途&#xff0c;因为日志本身是无止境的。 应用程序日志&#xff0c;安全日志&#xff0c;BI日志&#xff0c; 林肯日志 &#xff08;好吧&#xff0c;也…

Spring半注解半Xml

一、 Component 1.Component 标记了注解&#xff0c; 默认的名称是&#xff1a;简单类名&#xff0c;首字母小写UserDaoImpl -> userDaoImplUserServiceImpl -> userServiceImplComponent可以使用value属性指定对象的名称&#xff0c;相当bean标签的id属性 Component注解…

JDK 命令之 javadoc -- 生成API文档

文章目录命令简介命令选项中文乱码javadoc 命令实例进入源代码文件所在目录&#xff0c;解析指定的源代码文件&#xff0c;生成 API 文档解析指定包下的所有源码文件&#xff0c;生成 API 文档指定源文件根目录&#xff0c;再指定具体的包路径&#xff0c;解析其中的源码文件&a…

apache.camel_带有Spring Boot 2支持的Apache Camel 2.22发布

apache.camel今天&#xff0c;我们发布了最新的Apache Camel 2.22.0版本 &#xff0c;这是第一个正式完全支持Spring Boot 2的版本。这是一项重大的工作&#xff0c;因为针对像Apache Camel这样的大型框架将Spring Boot v1升级到v2付出了很多努力–感谢骆驼队和他们的贡献。 对…

纯注解的开发

使用纯注解开发 目录结构 JdbcConfiguration package com.itheima.Config;import com.mchange.v2.c3p0.ComboPooledDataSource; import org.apache.commons.dbutils.QueryRunner; import org.springframework.beans.factory.annotation.Value; import org.springframework.co…

IntelliJ IDEA forMac 如何生成项目的javadoc(API文档)

1.在菜单栏&#xff0c;点击 Tools -> Generate JavaDoc… 2.根据你自己的需要&#xff0c;设置解析源文件的范围、设置文档输出目录、设置资源的访问权限范围、字符编码、堆内存大小等。

vaadin_Vaadin Flow –奇妙的鹿

vaadin您可能知道&#xff0c;Vaadin是Java上最受欢迎的Web框架之一&#xff1a; https://zeroturnaround.com/rebellabs/java-web-frameworks-index-by-rebellabs/ https://javapipe.com/hosting/blog/best-java-web-frameworks/ 最近发布了此Web UI开发框架的新版本– Vaa…

Spring和Junit整合

一、引入依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version></dependency>二、在测试类中修改 &#xff08;1&#xff09;不带有配置文件的修改…

什么是stub文件_stub code

存根, 占位代码&#xff0c;占坑代码&#xff0c;桩代码&#xff0c;粘合代码&#xff0c;残存代码, 指满足形式要求但没有实现具体功能的占坑/代理代码。 stub code 给出的实现是临时性的/待编辑的。它使得程序在结构上能够符合标准&#xff0c;又能够使程序员可以暂时不编辑…

子类重写父类变量_为什么在子类中不重写超类的实例变量

子类重写父类变量当我们在父类和子类中创建一个具有相同名称的变量&#xff0c;并尝试使用持有子类对象的父类引用访问它时&#xff0c;我们会得到什么&#xff1f; 为了理解这一点&#xff0c;让我们考虑下面的示例&#xff0c;在该示例中&#xff0c;我们在Parent和Child类中…

Spring基于 XML 的声明式事务控制(配置方式)

一、引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4…

javadoc - Java API 文档生成器(Windows版本)

文章目录简介命令语法结构Javadoc Doclets术语带文档的类引用类外部引用类源文件源代码文件包注释文件概述注释文件其他未处理文件生成的文件基本内容页交叉参考页支持文件HTML 框架生成的文件结构文档注释注释源代码JAVADOC 标记author name-textdeprecated deprecated-textex…

光缆故障测试_简单的测试可以防止最严重的故障

光缆故障测试错误处理是软件开发中最困难且被忽略的部分之一&#xff0c;而且如果系统是分布式的&#xff0c;那么这将变得更加困难。 不错的论文写在“ 简单测试可以预防最关键的故障” 主题上。 每个开发人员都应该阅读本文。 我将尝试总结本文的主要内容&#xff0c;但建议…

使用aop解决事务问题(xml版)

一、引入依赖 pom.xml代码&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http:…

印象大使_基本服务-使用大使网关

印象大使这是我对Knative服务进行实验的延续&#xff0c;这次是围绕在Knative服务应用程序之上构建网关。 这建立在我之前的两篇文章的基础上- 使用Knative部署Spring Boot App以及在Knative中进行服务到服务的调用 。 为什么要在Knative应用程序之上使用网关 为了解释这一点&…

Eclipse 如何生成项目的javadoc(API 文档)

文章目录生成 javadoc 的三种方法乱码问题生成 javadoc 的三种方法 1.在项目列表中按右键&#xff0c;选择 Export&#xff0c;然后在 Export 对话框中选择 Java 下的 Javadoc&#xff0c;然后点击 Next 最后按 Finish 提交即可开始生成文档。 2.用菜单选择&#xff1a;File…

使用注解版AOP解决事务问题

一、注解版和xml版的区别 1、 通知的四种常用类型 &#xff08;1&#xff09;aop:before 作用&#xff1a; 用于配置前置通知。指定增强的方法在切入点方法之前执行 属性&#xff1a; method:用于指定通知类中的增强方法名称 ponitcut-ref&#xff1a;用于指定切入点的表达式…

Windows系统下彻底卸载MySQL数据库

1.正常卸载MySQL数据库 2.将 C:/ProgramData 目录下的子目录 MySQL 删除 注意&#xff1a;目录 ProgramData 是隐藏目录&#xff0c;你正常情况下看不到&#xff0c;你可以在文件地址栏输入 C:/ProgramData 进入该目录下。

ibm收购red hat_IBM将收购Red Hat:面向Java的初衷

ibm收购red hatOracle公司近九年前完成了收购Sun Microsystems的过程。 那是当时的大新闻&#xff0c;今天也宣布了类似的大新闻&#xff1a; IBM和Red Hat已经同意IBM收购Red Hat 。 IBM主页面宣布“ IBM收购Red Hat”。 然后&#xff0c;它说&#xff1a;“这将改变一切。” …