【问题标题】:How to determine default handling for key events fired by a ListView如何确定 ListView 触发的关键事件的默认处理
【发布时间】:2020-03-10 07:52:42
【问题描述】:

我想将KEY_PRESSED 事件的KeyEvent 处理程序(或过滤器)添加到ListView 以用于各种KeyCodes 和修饰符(shift 和/或控制键向下)。 JavaFX API 似乎为大多数(如果不是全部)提供了默认处理,但我无法确定:

  • 处理了哪些事件(和类型),或者
  • 如何处理它们(“处理代码”如何读取?),或
  • 处理是否通过属性设置实现(例如setOnKeyPressed(..)addEventFilter(..),或
  • 是否可以覆盖/替换默认处理。

这些信息是否容易获得?是否有资源以“简单的英语”方式回答这些问题?还是 JavaFX 开发的一般政策问题是这些操作对开发人员来说是不受限制的,并且必须在“原样,接受还是放弃”的基础上接受?

提前感谢您对此的任何意见。

【问题讨论】:

  • 没有记录哪些事件由控件处理以及控件的响应操作。但是,它们遵循标准的 UI/UX 实践(例如,对于文本输入控件,快捷键 +c 表示“复制到剪贴板”),甚至可以根据平台自定义自己(例如,在非 Mac 上,按钮可以通过“输入”键触发) .标准 JavaFX 控件分为三部分:Control 子类(模型)、Skin[Base] 实现(视图)和“行为”类(处理用户交互)。您可以查看行为类的源代码以了解它们的作用。
  • @Slaw 感谢您的回复。正如你暗示的那样,我查看了行为类 (ListViewBehavior),而我学到的东西是混合的。如果您不介意,我可以在聊天中更详细地解释字符限制不适用的情况。对于可能感兴趣的其他人,内置行为是在“原样,接受或放弃”的基础上提供的。如果你想偏离,你必须使用一个过滤器来消耗事件 ..AND .. 幸运地猜到要阻止哪些事件类型; API 不太清楚。
  • 行为本应与皮肤同时被提取到公共范围 - 但由于未解决的 api(和规范)问题而未能实现。从那时起,负责的开发人员离开了 oracle 并猜测行为 dev 发生了什么 .. ;) 因此,您可以根据是否允许使用内部东西来选择:是 - 反射地访问行为并修改其 inputMaps,否 - 获取来自 openjdk/jfx 的源,修改行为并编译您的自定义 fx。如果两者都禁止,您仍然可以 c&p 皮肤/行为并根据需要进行修改
  • @kleopatra 感谢您的回复。关于开发人员的有趣信息,这有助于解释为什么 JavaFX 的某些部分看起来像是在进行中,而其他部分则非常出色。您的建议很好,但由于这里涉及的大多数 API 都受到限制,我看不出它们是如何工作的。很乐意更详细地解释,但这需要比这里允许的字符限制更多的空间,所以你必须帮我打开一个聊天。在不同的东西上,你曾经做过 SwingX(或类似的东西)吗?如果是这样,那么我有一些你可能会感兴趣的东西。
  • 是的,一直是 SwingX 的主要开发人员之一 :)

标签: listview javafx event-handling


【解决方案1】:

按照@Slaw 的建议编辑问题,最好根据我所学提供答案。

目标是覆盖某些源自ListView 级别的KeyEvents 的默认处理。如果这不可能,那么确定确切地了解默认处理的工作原理会有所帮助,以便我了解我必须解决的问题。

JavaFX API 似乎在 ListViewBehavior 类中指定了这种处理,这是受限制的 API,并且因为它受到限制,访问它的最简单方法(根据我的经验)是通过 ListViewSkin 类创建并保存在创建ListView 时引用行为类。此引用是 private 字段(没有访问方法,例如 getBehavior()),因此只能在 ListViewSkin 的实例中访问。

默认行为安装在ListViewBehavior 构造函数中,通过将每个映射添加到ObservableList(命名为@ 987654334@) 获取地图;添加映射的代码在BehaviorBase 类中,它是ListViewBehavior 的父类。

@Kleopatra 提出了几个理论上可行的解决方案,除了 ListViewSkin 之外的所有类都是受限 API。这意味着无法访问该行为以使用反射,也无法从 openjdk/jfx 访问该行为。 @Kleopatra 的“从皮肤和行为复制粘贴”的建议应该是可行的(我没试过),但不实用;这将涉及大量工作,至少需要 1000 行代码(我的猜测),而这些工作应该不超过 30-50 行……不值得悲伤。

由于无法覆盖或替换默认处理(至少不是以实际方式),因此确切需要确定该行为的安装和操作方式。

上述KeyMappings 的行为在ListViewBehavior 类的private 方法中指定。这些方法本身很简单,在某种程度上它们是有帮助的。与行为如何运作有关的一些要点尚不清楚,例如:

  • 没有指示是否将特定行为添加为 处理程序或过滤器(即listView.addEventHandler(..)listView.addEventFilter(..)?这决定了当行为 实际运行,这反过来又会影响是否有任何反命令 可以安装自定义行为,如果是,那么安装在哪里;
  • 未指定为其添加行为的EventTypes;
  • 没有关于行为元素的顺序的指示 被添加也不至于订单是否可能取决于任何未披露的 条件;和
  • 无法保证私有中指定的行为 上述方法包含所有内置行为。

此列表可能并不详尽,可能存在其他人可能认为更重要的其他领域。但这些足以说明这如何使开发人员处于他们不得不盲目飞行的境地,......而且没有充分的理由。

如果不提及有一种方法可以阻止默认处理运行以支持自定义处理,这将是不公平的。这可以通过将KeyEvents 的过滤器添加到使用该事件的ListView 来实现。但是这个解决方案并不完美,因为上面列出的不确定性仍然存在。此外,消费该事件会产生意想不到的副作用吗?它会阻止默认行为在它应该运行的时候运行吗?简而言之,开发人员仍然是盲目的,因为这些不确定性只能通过设计和观察重复的试错练习的繁琐过程来澄清,以确定可能发生的确切情况。这是一种很好的编程方式吗?

最后,@Kleopatra 关于 JavaFX 行为如何最终公开以及所发生的事情的评论值得注意。根据我自己在这里和其他领域的观察,这些信息不足为奇。确实,它在很大程度上解释了为什么 JavaFX 虽然从整体上看是一个优秀的平台,但仍有许多缺点——除非得到解决——否则将阻止它有效地取代 Swing(提醒一下,这是其声明之一早在很久以前就由 Oracle 阐明的目标)。许多专家忘记了比我所知道的更多的东西,他们肯定不仅会提出异议,而且会强烈反对这一观点。但是,这并不能改变事实。

【讨论】:

  • 私有字段(没有访问方法,例如 getBehavior()),因此只能在 ListViewSkin 实例中访问 实际上.. 没有 :) 没有办法除了通过反射(需要在编译和运行时导出/打开),从皮肤或其他地方访问它。一旦你有了它,行为的 inputMap 的访问是公共的(好的,内部 api),你可以用你自己的替换映射。这是常见的做法,但高度依赖于实现。
  • 并且您错过了提取 openjdk/jfx 项目的源代码、替换任何行为的映射并编译您自己的版本的选项(在 wiki.openjdk.java.net/display/OpenJFX/Building+OpenJFX 中描述 - 它不再像几年前那样可怕以前 :) 然后捆绑并与您自己的项目一起分发。
猜你喜欢
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多