简体   繁体   English

自定义FocusTraversalPolicy类Java Swing

[英]Custom FocusTraversalPolicy class Java Swing

I'm working on setting new tab orders for multiple Panels accross an application. 我正在为一个应用程序中的多个面板设置新的标签顺序。 I want to create a new class that will allow me to handle to sorting much in the same way as the deprecated setNextFocusableComponent method would. 我想创建一个新类,该类将使我能够以与不赞成使用的setNextFocusableComponent方法相同的方式进行排序。 I'm creating a class that extends the DefaultTreversalPolicyClass and overloads the getComponentBefore and getComponentAfter methods. 我正在创建一个扩展DefaultTreversalPolicyClass并重载getComponentBefore和getComponentAfter方法的类。 On the panels themselves I want the implementation to be as simple as creating a new custom class (I'll call it CustomizedTabOrderPolicy) and then adding the components for which I want to specify the the tab order. 在面板上,我希望实现的过程像创建一个新的自定义类(我将其称为CustomizedTabOrderPolicy)一样简单,然后添加要为其指定制表符顺序的组件。 I do this via a convenience method on the CustomizedTabOrderPolicy class which allows me to add the components for which I want to specify tab order "link" to a Hashtable, I then create a copy of the hastable in which the key and value are switched. 我通过CustomizedTabOrderPolicy类上的便捷方法来执行此操作,该方法使我可以将要为其指定选项卡顺序“链接”的组件添加到Hashtable中,然后创建hastable的副本,在其中复制键和值。 I then use these hashtables to establish a forward and backward tab order "link" between the two components. 然后,我使用这些哈希表在两个组件之间建立前进和后退制表顺序“链接”。

the following is my custom class: 以下是我的自定义类:

import java.awt.Component;
import java.awt.Container;
import java.awt.DefaultFocusTraversalPolicy;
import java.util.Hashtable;

public class CustomizedTabOrderPolicy extends DefaultFocusTraversalPolicy {

    private Hashtable<Component, Component> exceptionsMap = new Hashtable<Component, Component>();
    private Hashtable<Component, Component> excpetionsMapReflection = new Hashtable<Component, Component>();
    private Component defaultComponent;
    private Component firstComponent;
    private Component lastComponent;

    public CustomizedTabOrderPolicy() {
    }

    @Override
    public Component getComponentAfter(Container container, Component component) {
        java.awt.Toolkit.getDefaultToolkit().beep();
        if (exceptionsMap.containsKey(component)) {
            return exceptionsMap.get(component);
        } else {
            return super.getComponentAfter(container, component);
        }
    }

    @Override
    public Component getComponentBefore(Container container, Component component) {
        if (exceptionsMap.containsValue(component)) {
            return excpetionsMapReflection.get(component);
        } else {
            return super.getComponentBefore(container, component);
        }
    }

    @Override
    public Component getDefaultComponent(Container container) {
        if (this.defaultComponent != null) {
            return this.defaultComponent;
        }
        return super.getDefaultComponent(container);
    }

    @Override
    public Component getFirstComponent(Container container) {
        if (this.firstComponent != null) {
            return this.firstComponent;
        }
        return super.getFirstComponent(container);
    }

    @Override
    public Component getLastComponent(Container container) {
        if (this.lastComponent != null) {
            return this.lastComponent;
        }
        return super.getLastComponent(container);
    }

    public void addNewException(Component origin, Component destination) {
        exceptionsMap.put(origin, destination);
        excpetionsMapReflection.put(destination, origin);
    }
    public void setDefaultComponent(Component defaultComponent) {
        this.defaultComponent = defaultComponent;
    }

    public void setLastComponent(Component lastComponent) {
        this.lastComponent = lastComponent;
    }

    public void setFirstComponent(Component firstComponent) {
        this.firstComponent = firstComponent;
    }
}

In order to implement this I am using the following on my JPanel: 为了实现这一点,我在我的JPanel上使用以下内容:

CustomizedTabOrderPolicy customPolicy = new CustomizedTabOrderPolicy();

customPolicy.addNewException(<component1>, <component2>);
customPolicy.addNewException(<component3>, <component4>);
customPolicy.addNewException(<component5>, <component6>);

this.setFocusTraversalPolicy(customPolicy);

I don't get any compiler or runtime errors, but it seems that my CustomTabOrderPolicy is not being used at all by the JPanel. 我没有收到任何编译器或运行时错误,但JPanel似乎根本没有使用我的CustomTabOrderPolicy。 When I insert breakpoints into the getComponentBefore and getComponentAfter methods, they are never triggered. 当我将断点插入getComponentBefore和getComponentAfter方法时,它们永远不会触发。 I am very new to working with Focus Traversal Policies so I'm wondering what I'm missing here... 我对使用焦点遍历策略非常陌生,所以我想知道我在这里缺少什么...

Ok so what I should have done is inherited FocusTraversalPolicy and not DefaultFocusTraversalPolicy and passed in a copy of the original Policy to revert to when there are no "exceptions". 好的,所以我应该做的是继承FocusTraversalPolicy而不是DefaultFocusTraversalPolicy,并传入原始Policy的副本以在没有“例外”时恢复原状。 I also need to set FocusCycleRoot to true on the panel in order for it to use my FocusTraversalPolicy. 我还需要在面板上将FocusCycleRoot设置为true,以使其使用我的FocusTraversalPolicy。 I now have it set up so that I have an instance of my CustomizedTabOrderPolicy on my AbstractJPanel base class so that all I need to call in the panel initialization is something like this: 现在,我已经对其进行了设置,以便在AbstractJPanel基类上拥有CustomizedTabOrderPolicy的实例,以便在面板初始化中需要调用的东西是这样的:

    this.setTabOrderEnabled(true);
    this.getCustomTabOrder().addNewException(component1, component2);
    this.getCustomTabOrder().addNewException(component2, component3);
    this.getCustomTabOrder().addNewException(component3, component4);

I've also changed the class itself somewhat to make it more effective. 我也对类本身进行了一些更改,以使其更有效。

public class CustomizedTabOrderPolicy extends FocusTraversalPolicy {

    private FocusTraversalPolicy oldPolicy;
    private Hashtable<Component, Component> exceptionsMap = new Hashtable<Component, Component>();
    private Hashtable<Component, Component> exceptionsMapReflection = new Hashtable<Component, Component>();
    private Component defaultComponent;
    private Component firstComponent;
    private Component lastComponent;

    public CustomizedTabOrderPolicy(FocusTraversalPolicy oldPolicy) {
        this.oldPolicy = oldPolicy;
    }

    public Component getComponentAfter(Container container, Component component) {
        if (component == this.getLastComponent(container)) {
            if (isValid(this.getFirstComponent(container))) {
                return this.getFirstComponent(container);
            } else {
                return this.getComponentAfter(container, this.getFirstComponent(container));
            }
        }
        if (exceptionsMap.containsKey(component) && isValid(exceptionsMap.get(component))) {
            return exceptionsMap.get(component);
        } else {
            return oldPolicy.getComponentAfter(container, component);
        }
    }

    public Component getComponentBefore(Container container, Component component) {
        if (component == this.getFirstComponent(container)) {
            if (isValid(this.getLastComponent(container))) {
                return this.getLastComponent(container);
            } else {
                return this.getComponentBefore(container, this.getLastComponent(container));
            }
        }
        if (exceptionsMapReflection.containsKey(component) && isValid(exceptionsMapReflection.get(component))) {
            return exceptionsMapReflection.get(component);
        } else {
            return oldPolicy.getComponentBefore(container, component);
        }
    }

    public boolean isValid(Component component) {
        if (component.isEnabled() && component.isVisible() && component.isFocusable()) {
            return true;
        } else {
            return false;
        }
    }
    public Component getDefaultComponent(Container container) {
        if (this.defaultComponent != null) {
            return this.defaultComponent;
        }
        return oldPolicy.getDefaultComponent(container);
    }

    public Component getFirstComponent(Container container) {
        if (this.firstComponent != null) {
            return this.firstComponent;
        }
        return oldPolicy.getFirstComponent(container);
    }

    public Component getLastComponent(Container container) {
        if (this.lastComponent != null) {
            return this.lastComponent;
        } else {
            return oldPolicy.getLastComponent(container);
        }
    }

    public void addNewException(Component origin, Component destination) {
        exceptionsMap.put(origin, destination);
        exceptionsMapReflection.put(destination, origin);
    }
    public void setDefaultComponent(Component defaultComponent) {
        this.defaultComponent = defaultComponent;
    }

    public void setLastComponent(Component lastComponent) {
        this.lastComponent = lastComponent;
    }

    public void setFirstComponent(Component firstComponent) {
        this.firstComponent = firstComponent;
    }
 }

efficient! 高效! I use this with a little modification to let it continue traversing when not isValid() (of course it should at least one isValid() component in your panel): 我使用此方法进行了一些修改,以使其在非isValid()时继续遍历(当然,它应该在面板中至少包含一个isValid()组件):

public Component getComponentAfter(Container container, Component component) {
    if (component == this.getLastComponent(container)) {
        if (isValid(this.getFirstComponent(container))) return this.getFirstComponent(container);
        else                                            return this.getComponentAfter(container, this.getFirstComponent(container));
    }
    if( exceptionsMap.containsKey(component) ) {
        component = exceptionsMap.get(component);
        if( isValid(component) ) return component;
        return this.getComponentAfter(container, component);
    }
    return oldPolicy.getComponentAfter(container, component);
}
public Component getComponentBefore(Container container, Component component) {
    if (component == this.getFirstComponent(container)) {
        if (isValid(this.getLastComponent(container))) return this.getLastComponent(container);
        else                                           return this.getComponentBefore(container, this.getLastComponent(container));
    }
    if( exceptionsMapReflection.containsKey(component) ) {
        component = exceptionsMapReflection.get(component);
        if( isValid(component) ) return component;
        return this.getComponentBefore(container, component);
    }
    return oldPolicy.getComponentBefore(container, component);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM