插件团队在桌面应用程序中配置JavaFX组件

与一个能记住您的习惯并感觉到您想要的应用程序进行交谈总是很高兴的。 遗憾的是,任何UI库或平台都只有基本功能和一组组件。 例如,如果表中的列不移动或无法对其进行排序,那么使用它的应用程序几乎不能被称为友好的。 幸运的是,今天您不会感到惊讶。 但是,并非每个程序都会记住此列的位置,并且在下一个会话中会将其显示在同一位置。 每次在SplitPane中设置分隔符的位置或输入相同的过滤器参数也可能很烦人。 通常,此类便利设施必须由开发人员自己提供。


有许多这样的看似很小的改进的例子,但是平台提供的解决方案只有两个,本质上它们是相似的:基于基础创建自己的组件,针对基础组件创建Skin ,重新定义行为。 这两种方法都不容易实现;此外,每个组件都需要编写自己的适配器组件。 我遇到了很多人,他们对这种方法更加熟悉和理解。


但是他远非唯一一个。 如果我们利用支持子节点的浏览器模板的平台的功能,并在添加或删除Node子图时通过一组插件运行,每个插件都在从事自己的特定工作,该怎么办? 一个可以在第二个会话中记住并恢复所有内容,另一个-上下文菜单可以更改指定的组件,并添加了复制文本的功能。 如果其中的某些内容不合适,其中一些会在文本末尾添加三个点,并且当您将鼠标悬停在鼠标上时,只有在不合适的情况下,它才会显示带有全文的提示。 最重要的是,此组件来自哪个库并不重要,我们是否可以从中继承并重新定义所需的行为。 在这种情况下,我们需要做的就是教导插件在必要时以不同的方式使用必要的组件。


这可能是儿童集合的侦听器:


private final ListChangeListener changeListener = (ListChangeListener<Node>) (ListChangeListener.Change<? extends Node> c) -> { if (c.next()) { c.getAddedSubList().forEach(this::applySettingsForNodeAndAddListenerForItsChild); } }; 

那将是每个修改后的Node的处理代码:


 private void applySettingsForNodeAndAddListenerForItsChild(Node n) { if (!checkApplySettings(n)) { apply(n); ObservableList<Node> children = getChildren(n); if (children != null) { addListnerForUpdateChildren(children); } markNodePropertyApplied(n); } } 

这是直接调用插件本身的代码,它在这种类型的组件上注册:


 public Node apply(Node node) { List<SettingsPlugin> settingsPlugins = settingsMap.get(Node.class); if (settingsPlugins != null) { for (SettingsPlugin plugin : settingsPlugins) { node = plugin.apply(node, userSettings.getSettings()); } } List<SettingsPlugin> settingList = settingsMap.get(node.getClass()); if (settingList != null) { for (SettingsPlugin plugin : settingList) { node = plugin.apply(node, userSettings.getSettings()); } } return node; } 

这是插件本身的接口:


 public interface SettingsPlugin { public Node apply(Node node, Map<String, Object> userSettings); } 

仅需要在Scene元素的Root子元素集合上注册一次侦听器,在子图的其余部分上,它将注册自己...


最近,我对桌面和Web应用程序平台的功能进行了类比。 知道如何在不同框架上实现这样的功能将是很有趣的。

Source: https://habr.com/ru/post/zh-CN422693/


All Articles