来自 JComponent 的 Java 阻塞焦点 [英] Java blocking focus from JComponent

查看:19
本文介绍了来自 JComponent 的 Java 阻塞焦点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为我的应用程序制作了一个 gui.JFrame 有 2 个 JPanel,panel1 &面板2.panel1 就是这样,一个带有自定义绘画的 JPanel,每 5 毫秒重绘一次.

panel2 是我第一次尝试 CardLayout 实现:它包含 JPanels subPanel1 &子面板2.subPanel1 包含一个 JComboBox 并添加到 panel2:panel2.add(subPanel1);.

subPanel2 具有 .setLayout(new CardLayout()); 命令,我向其中添加了 3 个新的 JPanel,以及适当的 itemListener 和所有内容.当然我也加了:panel2.add(subPanel2);

现在问题来了:在 Java 中聚焦组件.我了解方法 setFocusable(boolean)requestFocus().但我不能让他们以任何合乎逻辑的方式行事.

首先,它们的根本问题是:当组合框获得焦点时,我根本无法将其取消对焦(尝试用光标点击任何地方).

以下是我进行的实验:

1) 没有任何代码在整个应用程序中使用焦点,组合框从焦点开始,无论面板 1 和面板 2 以何种顺序添加到 JFrame.

2) 如果我设置了 panel1.setFocusable(true);(在它的构造函数中)它将以焦点开始

3) 如果我设置 panel1.setFocusable(false); 并请求焦点到它,它不会得到它.(唯一按预期工作的东西)

4) 如果我单独或任意组合将 panel2、subPanel1 或 subPanel2 设置为不可聚焦,它们仍然可以接收焦点(组合框,即唯一能够注册焦点的组件).

5) 如果我将组合框设置为不可聚焦,我仍然可以使用框的 itemListener 在 CardLayout 中的卡片之间滚动,但焦点不会粘在它上面.实际上 panel1 仍然注册键盘输入

所以我真的很困惑整个焦点"的事情.也许这不是我认为的那样?我想要做的是完全阻止与 panel2 的所有交互,直到标志(每 5 毫秒评估一次)为真.我是否正确地假设与 JPanels 不同,JComboBox 会自动具有一个 mousebuttonListener 以在单击时获得焦点?如果不是,那么如何完全禁用 JComboBox 和当前卡显示的所有组件?不可聚焦组件中的组件仍可聚焦是正常行为吗?

解决方案

听起来你真正想要使用的是 .setEnabled(false)

如果您需要将面板中的所有组件设置为禁用,那么您可以使用这样的方法来做到这一点:(可能不是 JComponents 的最佳方法,但可以轻松修改,如果需要,但这确实有效)

public static void setContainerAndChildrenEnabled(Container c, boolean b){Component[] allComps = c.getComponents();for(组件com:allComps){com.setEnabled(b);if(com 容器实例)setContainerAndChildrenEnabled((Container) com, b);}}

然后使用您要设置的面板和真或假来启用/禁用它.这还将为 Container

中的每个 Component 递归调用 setEnabled()

从文档中要注意两点:

<块引用>

  1. 注意:禁用轻量级组件不会阻止它接收 MouseEvents.

  2. 注意:禁用重量级容器会阻止此容器中的所有组件接收任何输入事件.但是禁用轻量级容器只会影响这个容器.

参见isLightweight()

I've made a gui for my application. The JFrame has 2 JPanels, panel1 & panel2. panel1 is just that, a JPanel with a custom painting that repaints itself every 5 ms.

panel2 is my first attempt at a CardLayout implementation: it contains JPanels subPanel1 & subPanel2. subPanel1 contains a JComboBox and is added to panel2: panel2.add(subPanel1);.

subPanel2 has the .setLayout(new CardLayout()); command, and I add 3 new JPanels into it, with appropiate itemListener and all. Of course I also add it: panel2.add(subPanel2);

Now to the problem: focusing components in Java. I have knowledge of methods setFocusable(boolean) and requestFocus(). But I can't make them behave in any logical way.

First, the root problem of them all: When the combobox gets the focus, I can't unfocus it at all (tried clicking everywhere with cursor).

Following are experiments I've conducted:

1) without any code speaking to focus throughout the application the combobox starts with the focus, no matter which order panel1 and panel2 are added to the JFrame.

2) if I set panel1.setFocusable(true); (in its constructor) it will start with the focus

3) if I set panel1.setFocusable(false); and also request focus to it, it doesn't get it. (only thing that works as expected)

4) if I set panel2, subPanel1, or subPanel2 unfocusable individually or in any combination, they can still receive focus (the combobox, that is, which is the only component able to register focus).

5) if I set the combobox unfocusable, I'm still able to scroll between the cards in the CardLayout with the box' itemListener, but the focus doesn't stick to it. In fact panel1 still registers keyboard-inputs

So really I am very confused about the whole 'focus' thing. Maybe it is not what I assume it is? What I am trying to do is entirely block all interaction with panel2 untill a flag (which is evaluated every 5 ms) is true. Am I correct to assume that unlike JPanels, the JComboBox automatically has a mousebuttonListener to gain focus when clicked? if no, then how do I completely disable the JComboBox and all components the current card is displaying? Is it normal behavior that components within an unfocusable component are still focusable?

解决方案

It sounds like what you really want to use is .setEnabled(false)

If you need to set all the components in a panel to be disabled then you can use a method like this to do it: (probably not the best method for JComponents but can be easily modified if required, but this does work)

public static void setContainerAndChildrenEnabled(Container c, boolean b)
{
    Component[] allComps = c.getComponents();
    for(Component com : allComps)
    {
        com.setEnabled(b);
        if(com instanceof Container)
            setContainerAndChildrenEnabled((Container) com, b);
    }
}

Then call it with the panel you want to set for and true or false to enable/disable. This will also recursively call setEnabled() for every Component within a Container

From the docs two points to note:

  1. Note: Disabling a lightweight component does not prevent it from receiving MouseEvents.

  2. Note: Disabling a heavyweight container prevents all components in this container from receiving any input events. But disabling a lightweight container affects only this container.

See isLightweight()

这篇关于来自 JComponent 的 Java 阻塞焦点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆