JavaFX - 如何创建简单的自定义绘制控件?

Tob*_*obi 6 user-interface javafx

我有把图形网络编辑器应用程序编程为大学项目的任务.为此,我需要三种类型的项目/控件.圆形,矩形和箭头连接其他形状(整个过程在某些方面有点像MS Visio).形状/控件需要一些额外的功能,如移动,缩放上下文菜单等.此外,我需要完全控制这些对象的图形表示,即我想自己"绘制"它们或者至少能够像我一样修改它们需要.

我正在使用JavaFX,几乎没有经验.所以我想知道,实现这些自定义控件的最佳方法是什么.它需要使用JDK 7,因此使用SkinBaseBehaviourBase不是一个选项,因为它们在JDK 8之前是私有的.

我在考虑子类化PathCanvas用作我的控件.但我对做出明智决定的影响知之甚少.

有人可以给我一些建议,要考虑哪些基类以及可能带来的影响?

多谢.

jew*_*sea 12

这个答案只是建议,这里没有正确或错误的答案.建议必须是固执己见的,并不适用于所有情况,如果您不同意,或者它不适用于您的情况,请忽略它.

对不起,但问题是开放式的,可能的答案很复杂.

我正在考虑将Path或Canvas子类化为我的控件.

别. 赞成合成而不是继承.有一个控件类,它实现控件的功能接口,无论后面的UI技术如何都可以工作.为控件类提供对皮肤类的引用,该皮肤类是控件的UI表示形式.外观将指定如何在给定状态下呈现控件(从关联的控件对象获取控件状态).此外,皮肤将响应用户操作,例如鼠标按下并指示控件基于鼠标按压改变其状态 - 因此皮肤知道它与哪个控件相关联,反之亦然.在控件类中有可绑定的属性来表示控件状态.

一个简单的例子是来自这个井字游戏实现的Square和SquareSkin.

例如,想象一个复选框控件.控件的可绑定属性可能是状态为(已选中,未选中,未确定)的枚举.外观可能会将复选框呈现为带有刻度线的方框,以表示已选中状态.或者,皮肤可以使用X渲染圆形边缘.皮肤可以使用您想要渲染复选框的任何技术,例如画布或节点集合.皮肤为鼠标点击,按键等注册监听器,并告诉复选框控件设置其检查状态.它还具有检查状态的监听器,并将根据该状态选择是否呈现检查标记.

关键是复选框的API接口只是一个带有检查状态的复选框控件类.处理UI的方式是从复选框API中抽象出来的,因此您可以根据需要交换UI实现,而无需更改任何其他代码.

Subclassing Path与子类化Canvas完全不同.对于subscribe的情况,我绝对赞成继承Shape节点(或Region)而不是Canvas.使用节点,您将自动拥有一个非常丰富的UI渲染和事件模型,可绑定属性集和绘制框架,这是Canvas无法获得的.如果您不使用节点,您可能最终会尝试以某种次标准方式重新创建和构建Node功能的某些部分.Canvas非常适合移植2D游戏或从其他框架移动图形引擎或构建像粒子系统这样的像素操纵器,但另外避免它.

考虑为您的控件皮肤使用布局窗格,例如StackPane或类似的东西.布局窗格是容器,因此您可以在其中放置内容并使用聚合和合成来构建更复杂的控件.布局窗格还可以帮助布局节点.

像Pane这样的子区域的任何子类都可以通过CSS设置为任意形状和颜色.这实际上是JavaFX中内置复选框(和其他控件)的工作方式.该复选框是两个区域的堆栈,一个是框,另一个是检查.两者都在CSS 中设置样式 - 在JavaFX 的modena.css样式表搜索.check-box.注意如何-fx-shape通过指定svg路径(可以在svg编辑器(如inkscape)中创建)来获取刻度形状.另请注意背景分层是如何用于聚焦环的.将CSS用于样式的优点是,您可以在不触及Java代码的情况下风格化地更改控件.

所以使用SkinBase和BehaviourBase不是一个选择

即使你决定不使用这些基类(即使你只针对Java 8+,我认为这是一个很好的决定),我认为值得研究JavaFX源代码中控件的设计.研究按钮或复选框,以便您可以看到专家如何做这些事情.另请注意,此类实现对于您的应用程序可能过度,因为您没有构建可重用的控件库.您只需要在应用程序范围内运行良好的东西(这就是我不一定建议为所有应用程序扩展SkinBase的原因).

至少阅读open-jfx wiki上的控件.

需要使用JDK 7

IMO,开发一个新的JavaFX应用程序以定位Java 7没有多大意义.Java 8有许多错误修复,还添加了新的有用功能.通常,Java 7是JavaFX应用程序的次优目标平台.如果将应用程序打包为独立应用程序,则可以随应用程序将所需的任何Java平台发布,因此目标平台无关紧要.

诸如WebStart或浏览器嵌入式应用程序(applet)之类的IMO部署技术(可以在系统上使用预先安装的Java运行时)是传统部署模式,对于大多数应用程序而言是最好的避免.

尽管如此,由于您的控制范围之外的某些限制,可能存在绝对必须拥有Java 7的情况,因此我想只是根据您的情况仔细评估.如果您有这样的约束并且必须构建一个稳定的遗留UI工具包,该工具包适用于多年前发布的运行时,您可以始终使用Swing.