用JavaFX编写自定义控件是一个简单直接的过程。 需要一个控件类来控制控件的状态(因此命名)。 外观需要控件的外观。 而且通常不是用于自定义外观CSS文件。
控件的常用方法是将其使用的节点隐藏在其外观类中。 例如, TextField控件使用javafx.scene.text.Text的两个实例。 一个用于常规文本,一个用于提示文本。 这些节点不能通过TextField API访问。 如果要获取对它们的引用,则需要在Node上调用lookup(String)方法。 到目前为止,一切都很好。 实际上,很难想到您实际上需要访问Text节点的用例。
但…
如果您开发复杂的自定义控件,那就完全不一样了。 FlexGanttFX Gantt图表框架就是一个示例。 GanttChart控件由许多其他复杂控件组成,并且遵循“ 关注点分离 ”的原则,这些控件包含所有与它们正常工作相关的方法和属性。 如果这些控件隐藏在甘特图的外观内,则将无法访问它们,而甘特图控件将需要实现大量的委托方法。 这将完全弄乱甘特图API。 因此, GanttChart类确实提供了其子控件的访问器方法,甚至提供了用于创建子节点的工厂方法。
例
以下屏幕截图显示了我当前正在为ControlsFX项目使用的新控件 。 我称之为ListSelectionView ,它具有两个ListView实例。 用户可以通过双击项目或使用中间的按钮将项目从一个列表移动到另一个列表。
列表视图是复杂的控件。 他们有自己的数据和选择模型,他们自己的单元工厂,他们触发事件等等。 所有这些事情我们都可能想要自定义或聆听。 如果视图隐藏在皮肤类中,则很难做。 解决方案是通过受保护的工厂方法在控件类内部创建列表视图,并提供访问器方法。
以下代码片段显示了可以使用的模式:
public class ListSelectionView<T> extends Control {private ListView<T> sourceListView;private ListView<T> targetListView;public ListSelectionView() {sourceListView = createSourceListView();targetListView = createTargetListView();}protected ListView<T> createSourceListView() {return new ListView<>();}protected ListView<T> createTargetListView() {return new ListView<>();}public final ListView<T> getSourceListView() {return sourceListView;}public final ListView<T> getTargetListView() {return targetListView;}
}
工厂方法可用于创建标准ListView实例并在此处配置它们,或返回已经存在的ListView专业化对象。 一家名为ACME的公司可能已经提供了一套标准的控件(用于实现公司的营销概念)。 然后,工厂方法可能会返回一个称为ACMEListView的控件。
翻译自: https://www.javacodegeeks.com/2014/07/javafx-tip-10-custom-composite-controls.html