gpt4 book ai didi

java - 计算窗口内两个 Swing 组件的焦点遍历距离

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:22:13 24 4
gpt4 key购买 nike

原帖

我想以编程方式确定在当前窗口中从一个 Swing 组件(拥有焦点)转到另一个 Swing 组件需要多少次键盘敲击(无论是否使用 Tab 键和/或箭头键都无关紧要)。每笔画应该增加1的距离;如果无法访问该组件,则结果应为 -1。

由于找不到实用方法,我想到了以下签名:

public static int getFocusTraversalDistance( Component from, Component to )

天真地,我会从通过 getFocusCycleRootAncestor() 获取 fromContainer 开始。 .之后,我将使用 getFocusTraversalPolicy() 获取 FocusTraversalPolicy并使用 getComponentAfter(Container, Component) 遍历组件分别getComponentBefore(Container, Component) .

但是,我对 Swing/AWT 焦点子系统不是很熟悉,我想知道是否有更优雅的方法?

编辑 #1

我需要这些信息的原因是我目前正在撰写的硕士论文。这个想法是通过机器学习来增强基于 GUI 的猴子测试。训练模型不是随机选择组件,而是尝试根据历史用户/测试人员轨迹“推荐”组件。我为此使用的功能之一是前一个目标组件和可能的目标组件之间的焦点遍历距离。

编辑 #2

感谢 camickr 的宝贵意见,我目前正在使用以下算法:

public static int getFocusTraversalDistance( Component from, Component to ) {
if ( from.equals( to ) ) {
return 0;
}

final Container root = from.getFocusCycleRootAncestor();

if ( root == null ) {
return -1;
}

final FocusTraversalPolicy policy = root.getFocusTraversalPolicy();
final HashSet<Component> visited = new HashSet<>();
Component before = from;
Component after = from;
int distance = 1;

while ( true ) {
if ( before != null ) {
visited.add( before );
before = policy.getComponentBefore(
before.getFocusCycleRootAncestor(), before );
if ( to.equals( before ) ) {
return distance;
}
}

if ( after != null ) {
visited.add( after );
after = policy.getComponentAfter(
after.getFocusCycleRootAncestor(), after );
if ( to.equals( after ) ) {
return distance;
}
}

if ( before == null && after == null
|| visited.contains( before ) && visited.contains( after ) ) {
return -1;
}

distance++;
}
}

到目前为止它似乎有效,但实际上不可聚焦的组件可能会产生奇怪的结果。 AWT focus subsystem doc说“[...] 所有组件都从此 [ Component#isFocusable() ] 方法返回 true。”即使像 JLabel 这样的组件也会返回 true,尽管(据我所知)它实际上无法获得焦点并且 Component#hasFocus()始终为 false

如果有人感兴趣,我可以设置一个带有完整功能测试套件的 GitHub 项目。

最佳答案

this question is related to Swing only, don't worry—any help is appreciated

我已经说过这听起来是一种合理的方法。我唯一不确定的是,当您有多个嵌套面板时,该方法是否有效。或者至少如果您必须为每个容器获取焦点遍历策略,它可能会变得更加复杂。

您可以尝试查看 KeyboardFocusManager 看看它是否有帮助。

我能想到的唯一其他方法是实际切换表单上的所有组件并将每个组件添加到 ArrayList。然后您的 getFocusTraversalDistance(...) 将使用 ArrayList 而不是 FocusTraversalPolicy。当然,这有一个问题,即组件实际上会获得焦点,并且可以调用 focusGained/focusLost 代码。

或者将这两种方法结合起来。那就是使用您的方法来使用焦点遍历策略,但仅在创建框架时执行此方法来构建 ArrayList。然后您的 getFocusTraversalDistance(...) 可以引用 ArrayList,这应该会提高效率。

关于java - 计算窗口内两个 Swing 组件的焦点遍历距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44087822/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com