catching focus leaving a jpanel
Hi,
I have a JPanel with a number of children (a form). This panel can in turn be nested in a larger form. I need to be able to detect when focus is being transfered from outside of the panel to any of its children, and when focus is being transfered from inside the panel out. When the focus is transfered out, I also want to be able to display a confirmation box with an option to cancel the focus transfer.
Any ideas on how to implement this?
Thanks
Dmitry
[490 byte] By [
dberanskya] at [2007-11-27 0:15:19]

# 7
hunter, what you're suggesting won't work. Trying to change focus (e.g. by showling a dialog box) while in the middle of processing another focus event will cause a deadlock of the AWT event thread. That's why InputVerifier was added to Swing a few JDKs back. An input verifier gets activated before focus transfer takes place, thus making it possible to pop a dialog box.
abillconsl, thanks, I'll look into that. that thought has crossed my mind, but for whatever reason I immediately dismissed it. I guess this is worth an investigation.
# 8
Looking back in some old code, I found this (and this worked just fine for me):
KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
// had som IFs and ELSEs here, you could put in whatever you'd like.
System.out.println("Focus change. From " + e.getOldValue() + " to " + e.getNewValue());
}
}
);
Just put this anywhere inside code being executed by the EDT.
rebola at 2007-7-11 22:02:01 >

# 10
well, it doesn't get any more brittle than this.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Testing
{
JPanel northPanel, southPanel;
public void buildGUI()
{
northPanel = getFormPanel();
southPanel = getFormPanel();
FormPanelListener fpl = new FormPanelListener();
Component[] comp = southPanel.getComponents();
for(int x = 0, y = comp.length; x < y; x++) comp[x].addFocusListener(fpl);
JFrame f = new JFrame();
f.getContentPane().add(northPanel,BorderLayout.NORTH);
f.getContentPane().add(southPanel,BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public JPanel getFormPanel()
{
JPanel p = new JPanel(new GridLayout(4,1));
p.add(new JTextField(10));
p.add(new JTextField(10));
p.add(new JTextField(10));
p.add(new JButton("OK"));
return p;
}
class FormPanelListener implements FocusListener
{
int counter;
public void focusGained(FocusEvent fe)
{
counter++;
}
public void focusLost(final FocusEvent fe)
{
counter--;
ActionListener al = new ActionListener(){
public void actionPerformed(ActionEvent ae){
if(counter < 1)
{
int continueAction = JOptionPane.showConfirmDialog(null,
"Leaving south panel, continue?","",JOptionPane.OK_CANCEL_OPTION);
if(continueAction != JOptionPane.OK_OPTION)
{
((JComponent)fe.getSource()).requestFocusInWindow();
}
}
}
};
javax.swing.Timer timer = new javax.swing.Timer(100,al);
timer.setRepeats(false);
timer.start();
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new Testing().buildGUI();
}
});
}
}