1

我有一个 JFrame,其中包含通常的各种面板和小部件,并且我有一个 JPanel,我将其用作该 JFrame 的 glassPane。我希望能够在可见时将键盘焦点遍历限制在 glassPane 中的组件上。

我的问题可能会也可能不会因为后台线程启动一个进程导致出现进度对话框并随后消失这一事实而变得更加复杂,这会从我的 glassPane 中的一个小部件中窃取焦点,但将其返回到我的 glassPane 下的某个小部件。

我尝试将 JFrame 的焦点遍历策略设置为仅允许 glassPane 被聚焦的策略,但这似乎没有任何效果。(也许我做错了?)

任何帮助,将不胜感激。

4

5 回答 5

3

我将使我的评论成为答案,因为我相信这是解决您问题的方法:

也许更好的选择是使用CardLayout来简单地交换视图而不是玻璃窗格或对话框,因为这种情况似乎不适合玻璃窗格的使用。如果您使用 CardLayout,则不必想出一个 kludge(摆弄焦点遍历)来修复另一个 kludge 的副作用(使用玻璃窗格来处理它不打算用于的事情)。

如果您不熟悉它,CardLayout 将允许您轻松地交换 GUI 中的组件,并且通常用于交换持有复杂 GUI 的 JPanel,当用户从一个主要程序状态转到另一个主要程序状态时。我认为这对你的目的来说是完美的,并且可以让你不必担心你的注意力问题。

于 2012-04-03T21:35:14.807 回答
3

正如我在评论中提到的,我可能会选择 J/X/Layer - 但如果自定义 FTP 确实是您的上下文中唯一缺少的部分,那么这是一个解决方案。

要从焦点遍历中排除组件,请在自定义 FTP 的接受方法中拒绝它们。下面是一个示例,如果 glassPane 可见,则拒绝所有不是 glassPane 子级的组件(注意:这过于简单,因为它只处理直接子级,实际代码必须沿着父链向上走,直到它碰到玻璃板与否)

public static class FTP extends LayoutFocusTraversalPolicy {

    @Override
    protected boolean accept(Component comp) {
        JFrame window = (JFrame) SwingUtilities.windowForComponent(comp);
        if (hasVisibleGlassPane(window)) {
            return comp.getParent() == window.getGlassPane();
        }
        return super.accept(comp);
    }

    private boolean hasVisibleGlassPane(JFrame window) {
        return window != null && window.getGlassPane() != null
                && window.getGlassPane().isVisible();
    }

}
于 2012-04-04T09:27:42.233 回答
2

尝试.setFocusable(false)在 glassPane 可见时调用您想要忽略的 JFrame(或者最坏的情况是调用其中的所有组件)。

于 2012-04-03T20:56:49.797 回答
0

当我与客户讨论时,他给了我同样的要求。所以我决定在我的项目中使用 JLayer 和 LayeredPane,并将所有这些组件作为我实现以下代码的简单解决方案,它可能会对您的项目有所帮助。

public YourConstructor() {
    yes.addFocusListener(new FocusAdapter() {
        public void focusLost(FocusEvent fe) {
            if (!no.hasFocus()) {
                no.requestFocusInWindow();
            }
        }
    });

    no.addFocusListener(new FocusAdapter() {
        public void focusLost(FocusEvent fe) {
            if (!yes.hasFocus()) {
                yes.requestFocusInWindow();
            }
        }
    });
}

@Override
public void setVisible(boolean visibility) {
    super.setVisible(visibility);
    if (visibility) {
        yes.requestFocusInWindow();
    }
}
于 2013-04-23T17:00:08.443 回答
0

以克娄巴特拉的回答为基础,帮助处于类似情况的其他人;我有一堆我不想关注的自定义挥杆组件(有时仅在它们不可编辑时)。我最终得到了这个:

/**
 * A custom focus traversal policy to make focus traversal inside a container to ignore some swing components.<br /><br />
 * 
 * <b>Ignored components:</b><br />
 * - <code>CustomComponent1</code> components<br />
 * - <code>CustomComponent2</code> components that are not editable<br /><br />
 * 
 * <b>Usage:</b><br /><br />
 * <code>Container.setFocusTraversalPolicy(new CustomFocusTraversalPolicy());</code>
 */
public class CustomFocusTraversalPolicy extends LayoutFocusTraversalPolicy {

    private static final long serialVersionUID = 1L;

    protected boolean accept(Component c) {

        if(c instanceof CustomComponent1) {
            return false;
        }

        if(c instanceof CustomComponent2) {

            CustomComponent2 t = (CustomComponent2) c;

            if(!t.isEditable()) {
                return false;
            }
        }

        return super.accept(c);
    }

}

请注意,需要为每个设置策略Container(我为每个Window创建的都设置了):

Window window = new JFrame(); // Or JDialog; both subclasses of Container and Window
window.setFocusTraversalPolicy(new CustomFocusTraversalPolicy());
于 2019-03-19T07:34:58.650 回答