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?

Java Code:
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!