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. I'm creating a class that extends the DefaultTreversalPolicyClass and overloads the getComponentBefore and getComponentAfter methods. 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. 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. 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:
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. When I insert breakpoints into the getComponentBefore and getComponentAfter methods, they are never triggered. 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". I also need to set FocusCycleRoot to true on the panel in order for it to use my 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:
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):
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);
}
链接地址: http://www.djcxy.com/p/23988.html
上一篇: 获取在java Map中给定值的索引或键