Hello!
I have to find place where I can allow / prohibit focus transfer.
I have to know both components - component which loses focus and component which required focus.
I need a place (or all places) to be tracked on tabbing, mnemonic key press, mouse press.
It seems like VetoableChangeListener method vetoableChange(...) is the right place for me.
But I encountered strange behaviour. See code below.
When I change VETOFOCUSCHANGE = true, vetoableChange(...) is not executed anymore (no console output).
However focus change is prohibited.
Why method vetoableChange(...) is not executed? Or it is? Why there is no console output?
import java.awt.*; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; import javax.swing.*; public class VetoableFocus extends JDialog implements FocusListener { private static int counter = 0; //*********************************************** //Change this to test FocusVetoableChangeListener private static boolean VETOFOCUSCHANGE = false; //*********************************************** class FocusVetoableChangeListener implements VetoableChangeListener { public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { System.out.println((++counter) + " " + "VetoableChange " + evt.getPropertyName()); Component oldComp = (Component) evt.getOldValue(); Component newComp = (Component) evt.getNewValue(); if ("focusOwner".equals(evt.getPropertyName())) { System.out.println((++counter) + " " + "Vetoable 'focusOwner' change " + oldComp + " >> " + newComp); } if (VETOFOCUSCHANGE) { throw new PropertyVetoException("message", evt); } } } class MyTextField extends JTextField { private String name; public MyTextField(String name) { this.name = name; setText(name); } @Override public boolean requestFocusInWindow() { System.out.println((++counter) + " " + this + " requestFocusInWindow"); return super.requestFocusInWindow(); //return false; } @Override public void requestFocus() { System.out.println((++counter) + " " + this + " requestFocus"); super.requestFocus(); } @Override public void transferFocus() { Container focusCycleRoot = getFocusCycleRootAncestor (); FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy (); Component next = policy.getComponentAfter (focusCycleRoot, this); System.out.println((++counter) + " " + this + " transferFocus to " + next); super.transferFocus(); } @Override public String toString() { return name; } }; public VetoableFocus() { KeyboardFocusManager.getCurrentKeyboardFocusManager().addVetoableChangeListener(new FocusVetoableChangeListener()); setLayout(new BoxLayout(VetoableFocus.this.getContentPane(), BoxLayout.Y_AXIS)); JTextField text1 = new MyTextField("text1"); text1.addFocusListener(this); JLabel label1 = new JLabel("label1"){ public String toString() { return "label1"; } }; label1.setDisplayedMnemonic('1'); label1.setLabelFor(text1); JTextField text2 = new MyTextField("text2"); text2.addFocusListener(this); JLabel label2 = new JLabel("label2"){ public String toString() { return "label2"; } }; label2.setDisplayedMnemonic('2'); label2.setLabelFor(text2); add(label1); add(text1); add(label2); add(text2); setSize(new Dimension(300, 300)); setVisible(true); } public String toString() { return "Dialog"; } @Override public void focusGained(FocusEvent evt) { System.out.println((++counter) + " " + evt.getSource() + " focus gained"); } @Override public void focusLost(FocusEvent evt) { System.out.println((++counter) + " " + evt.getSource() + " focus lost"); } public static void main(String[] args) { new VetoableFocus(); } }
Thank you in advance!