|
|
||
Craig Castelaz's BlogThe best laid plansPosted by castelaz on August 10, 2004 at 07:47 AM | Comments (0)I recently started a new assignment at work to improve field validation in our primary Swing application. Like many older GUI based applications, our product relies heavily upon the lost focus event to trigger field validation. In other words, we verify the value of a component, such as a JTextField, inside its lost focus event. The problem, as you might guess, is that the verfication occurs too late. We've already lost focus. While it is easy enough to request that focus return to the offending component if it contains invalid data, the new focus owner may be unable to relinquish it for some reason. In addition, lost focus events will frequently cascade which makes managing the validation process difficult. For instance, there may be times when we need to ignore validation errors. The best example of this is the Cancel button. Since were about to throw away all the changes the user made, it is safe to disregard any validation errors. Correctly turning on and off the validation flag can become a real challenge, especially in a blizzard of lost focus events.
As I investigated alternatives, I quickly came upon the
Without belaboring the point,
Although I couldn't use the solution directly, it did give me another idea. Basically, the problem is that the button gets the "click" before it calls the other component's I already know that this technique does not work with JInternalFrames, which maintain their own GlassPane components. In addition, I have not tested either default button processing or mnemonic traversal. While the solution may not address everyone's needs, it does appear to work in plain vanilla JFrames and JDialogs.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GlassPaneDemo extends JComponent implements MouseListener {
Container contentPane;
public GlassPaneDemo(Container contentPane) {
addMouseListener(this);
this.contentPane = contentPane;
}
public void mousePressed(MouseEvent me) {
redispatchMouseEvent(me, false);
}
public void mouseReleased(MouseEvent me) {
//buttons appear depressed until they receive mouse release
redispatchMouseEvent(me, false);
}
public void mouseClicked(MouseEvent me) {
}
public void mouseEntered(MouseEvent me) {
}
public void mouseExited(MouseEvent me) {
}
private void redispatchMouseEvent(MouseEvent me, boolean repaint) {
Point containerPoint = SwingUtilities.convertPoint(this, me.getPoint(), contentPane);
JComponent targetComponent =
(JComponent)SwingUtilities.getDeepestComponentAt(contentPane, containerPoint.x, containerPoint.y);
if (targetComponent == null) {
return;
}
if (targetComponent.isFocusOwner()) {
redispatchEvent(targetComponent, me);
return;
}
else {
JComponent currentComponent =
(JComponent)KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if ((currentComponent != null)
&& (currentComponent.getInputVerifier() != null)
&& (targetComponent.getVerifyInputWhenFocusTarget())) {
if (! currentComponent.getInputVerifier().verify(currentComponent)) {
// not verified, so eat the mouse event
}
else {
redispatchEvent(targetComponent, me);
}
}
else {
redispatchEvent(targetComponent, me);
}
}
}
private void redispatchEvent(Component component, MouseEvent me) {
Point componentPoint = SwingUtilities.convertPoint(this, me.getPoint(), component);
component.dispatchEvent(new MouseEvent(component,
me.getID(),
me.getWhen(),
me.getModifiers(),
componentPoint.x,
componentPoint.y,
me.getClickCount(),
me.isPopupTrigger()));
return;
}
public static void main(String[] args) {
JFrame frame = new JFrame("GlassPane Demo");
JTextField textField = new JTextField("this is a textfield");
textField.setInputVerifier(new TextVerifier());
JButton cancelButton = new JButton("Cancel");
cancelButton.setVerifyInputWhenFocusTarget(false);
JButton saveButton = new JButton("Save");
JPanel mainPanel = new JPanel();
mainPanel.add(textField);
mainPanel.add(cancelButton);
mainPanel.add(saveButton);
frame.getContentPane().add(mainPanel);
GlassPaneDemo gpd = new GlassPaneDemo(frame.getContentPane());
frame.setGlassPane(gpd);
gpd.setVisible(true);
frame.pack();
frame.setSize(400, 200);
frame.show();
}
}
class TextVerifier extends InputVerifier {
public boolean verify(JComponent component) {
if (component instanceof JTextField) {
return ((JTextField)component).getText().equalsIgnoreCase("pass");
}
return true;
}
}
Bookmark blog post: CommentsComments are listed in date ascending order (oldest first) | Post Comment | ||
|
|