什么导致组件requestFocus有时失败? [英] what causes component requestFocus to fail sometimes?

查看:168
本文介绍了什么导致组件requestFocus有时失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个jDialog,其中包含一些需要专注的字段。

我看到一些奇怪的行为,有时聚焦失败,如果你点击标签键,你可以在下面的父窗口看到焦点的变化,所以清楚的焦点没有被转移。



我读了有趣的文章(由camickr)
http://tips4java.wordpress.com/2010/03/ 14 / dialog-focus /
但是这并没有解决问题。



使用这个监听器,我很容易添加调试来试试看看发生了什么...

  public class RequestFocusListener implements AncestorListener 
{
private boolean removeListener;
protected static org.slf4j.Logger logger = LoggerFactory.getLogger(RequestFocusListener.class);

/ *
*方便的构造函数。监听器只使用一次,然后从组件中删除
*。
* /
public RequestFocusListener(){
this(true);
}

/ *
*构造函数控制这个监听是否可以被使用一次或
*多次。
*
* @param removeListener当为true时,这个侦听器只被调用一次
*否则可以多次调用。
* /
public RequestFocusListener(boolean removeListener){
logger.debug(Creating RequestFocusListener,removeListener =+ removeListener);
this.removeListener = removeListener;

$ b @Override
public void ancestorAdded(AncestorEvent e)
{
logger.debug(ancestorAdded detected);
JComponent component = e.getComponent();
logger.debug(请求焦点);
布尔成功= component.requestFocusInWindow();
logger.debug(请求重点在窗口结果是:+成功);
if(!success){
logger.debug(KeyboardFocusManager says focus failed.\\\
focus owner is+ KeyboardFocusManager.getCurrentKeyboardFocusManager()。getFocusOwner());
logger.debug(displayable =+ component.isDisplayable());
logger.debug(lightweight =+ component.isLightweight());
logger.debug(enabled =+ component.isEnabled());
logger.debug(focusable =+ component.isFocusable());
logger.debug(showing =+ component.isShowing());
logger.debug(isRequestFocusEnabled =+ component.isRequestFocusEnabled());
} else {
logger.debug(KeyboardFocusManager说我们有焦点,焦点所有者是+ KeyboardFocusManager.getCurrentKeyboardFocusManager()。getFocusOwner());

if(removeListener){
component.removeAncestorListener(this);



@Override
public void ancestorMoved(AncestorEvent e){
}

@Override
public void ancestorRemoved(AncestorEvent e){
}

}



然后,我将监听器添加到JDialog的主面板中的一个组件

  radioButton。 addAncestorListener(new RequestFocusAncestorListener()); 

我得到的输出显示:

 displayable = true 
lightweight = true
enabled = true
focusable = true
showing = true
isRequestFocusEnabled = true

单步执行代码以查看请求失败的原因,我看到它停在Component.requestFocusHelper上:

  boolean success = peer.requestFocus(this,temporary,focusedWindowChangeAllowed,time,cause); 

我已阅读该组件必须是可显示/可见/可聚焦的),但调试显示可以。

任何人都可以阐明什么可能会导致requestFocus失败吗? (并把焦点留在调用父面板,在这种情况下,在一个Jtable)

提前抱歉没有提供一个完整的SSCCE,我试图重现这个一个独立的例子,不能让它失败一致。

我欣赏任何想法/提示。




followup -



好像我第一次打开对话框,就会关注对象,然后关闭并重新打开焦点并不总是被设置的对话框。



有趣的是,在关闭对话框之后,如果在再次打开对话框之前更改父对象的焦点,焦点似乎总是被设置。 b

解决方案

有一些可能的原因,焦点请求将失败。 ,Java Docs for Component#requestFocus 实际状态


因为焦点行为这个方法是依赖于平台的,强烈建议
开发者在使用
的时候使用requestFocusInWindow。




这个组件必须是可显示的,可聚焦的,可见的以及所有
祖先(除了顶层窗口)必须是可见的
为要被授予的请求

为了使组件成为可调焦的,组件和所有祖先必须有效(可显示)。我看到很多常见的错误之一是人们在创建一个新窗口时使用 requestFocus requestFocusInWindow 该窗口实际上可以显示在屏幕上( setVisible 不能保证该窗口将立即可见,只有将来的一段时间才能看见) p>

在这种情况下,最好的方法是使用 WindowListener 并监视 windowOpened 事件。事件然后,我会试图使用 SwingUtilities#invokeLater 来确保窗口实际上可以在屏幕上显示。



另一个问题是依靠 isDisplayable 。这个方法可能会返回 true ,即使组件打开的窗口不是(显示在屏幕上)。

组件在连接到本机屏幕资源时变得可显示。当祖先窗口被打包或显示时,可能会发生这种情况...事实上,我很难确定这种情况的发生时间。



Update



我还应该补充说, requestFocus 就是这个请求。可能是由于另一个字段拒绝投降(例如当字段 InputVerifier#shouldYieldFocus 返回时),焦点管理子系统可能否决请求。假


I have a jDialog which contains some fields that need to get focused.

I am seeing some strange behaviour where sometimes the focusing fails, and if you hit the tab key you can see the focus change in the underlying parent window below, so clearly the focus did not get transferred.

I read the interesting article (by camickr) on focusing: http://tips4java.wordpress.com/2010/03/14/dialog-focus/ but that did not solve the problem.

Using that listener though, I was easily able to add debugging to try and see what is occurring...

public class RequestFocusListener implements AncestorListener
{
private boolean removeListener;
    protected static org.slf4j.Logger logger = LoggerFactory.getLogger(RequestFocusListener.class);

/*
 *  Convenience constructor. The listener is only used once and then it is
 *  removed from the component.
 */
public RequestFocusListener() {
    this(true);
}

/*
 *  Constructor that controls whether this listen can be used once or
 *  multiple times.
 *
 *  @param removeListener when true this listener is only invoked once
 *                        otherwise it can be invoked multiple times.
 */
public RequestFocusListener(boolean removeListener) {
        logger.debug("creating RequestFocusListener, removeListener = " + removeListener);
    this.removeListener = removeListener;
}

@Override
public void ancestorAdded(AncestorEvent e)
{
        logger.debug("ancestorAdded detected");
        JComponent component = e.getComponent();
        logger.debug("requesting focus");
        boolean success = component.requestFocusInWindow();
        logger.debug("request focus in window result was: " + success);
        if (!success) {
            logger.debug("KeyboardFocusManager says focus failed.\nfocus owner is " + KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner());
            logger.debug("displayable="+component.isDisplayable());
            logger.debug("lightweight="+component.isLightweight());
            logger.debug("enabled="+component.isEnabled());
            logger.debug("focusable="+component.isFocusable());
            logger.debug("showing="+component.isShowing());
            logger.debug("isRequestFocusEnabled="+component.isRequestFocusEnabled());
        } else {
            logger.debug("KeyboardFocusManager says we got focus.  focus owner is " + KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner());
        }
        if (removeListener) {
    component.removeAncestorListener( this );
        }
}

@Override
public void ancestorMoved(AncestorEvent e) {
    }

@Override
public void ancestorRemoved(AncestorEvent e) {
    }

}

Then I added the listener to a component in the main panel of the JDialog

radioButton.addAncestorListener(new RequestFocusAncestorListener());

The output I am getting shows:

displayable=true
lightweight=true
enabled=true
focusable=true
showing=true
isRequestFocusEnabled=true

Stepping through the code to see what is making the request fail, I see it stops in Component.requestFocusHelper on:

boolean success = peer.requestFocus(this, temporary, focusedWindowChangeAllowed, time, cause);

I have read that the component must be displayable/visible/focusable) but the debugging shows that is ok.

Can anyone shed any light on what else might cause the requestFocus to fail? (and leave the focus in the calling parent panel, in this case in a jtable)

Sorry in advance for not providing a complete SSCCE, I have tried to reproduce this in a standalone example and can't get it to fail consistently.

I appreciate any thoughts/tips.


followup -

It seems like the first time I open the dialog, it gets focus, and then when I close and reopen the dialog the focus does not always get set.

Interestingly, after closing the dialog, if I change focus in the parent before opening the dialog again, the focus seems to always get set.

解决方案

There are any number of possible reasons a request for focus will fail.

To start with, the Java Docs for Component#requestFocus actually states

Because the focus behavior of this method is platform-dependent, developers are strongly encouraged to use requestFocusInWindow when possible.

And

This component must be displayable, focusable, visible and all of its ancestors (with the exception of the top-level Window) must be visible for the request to be granted

In order for a component to become focusable, the component and all it's ancestors must be valid (displayable). One of the common mistakes I see a lot is people using requestFocus or requestFocusInWindow when they create a new window, but before that window could actually be shown on the screen (setVisible does not guarantee that the window will be immediately visible, only that some time in the future it will become visible).

The best approach in this situation is to use a WindowListener and monitor for windowOpened event. Event then, I'd be tempted to use a SwingUtilities#invokeLater to make sure the window is actually displayable on the screen.

The other issue is relying on isDisplayable. This method may return true even when the window that the component is on is not (displaying on the screen).

A component becomes displayable when it is connected to a native screen resource. This can happen when it's ancestor window is either packed or made visible ... In fact I've found it very difficult to determine exactly when this might occur.

Update

I should also add that requestFocus is just that, a "request". It is possible that the focus management sub system may veto the request because another field has refused to surrender focus (such as when the fields InputVerifier#shouldYieldFocus returns false)

这篇关于什么导致组件requestFocus有时失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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