Java Tutorial/Swing Event/FocusListener

Материал из Java эксперт
Перейти к: навигация, поиск

FocusListener and FocusEvent

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * FocusEventDemo.java
 *
 */
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FocusEventDemo extends JFrame implements FocusListener {
  final static String newline = "\n";
  JTextArea display;
  public FocusEventDemo(String name) {
    super(name);
  }
  public void addComponentsToPane(final Container pane) {
    GridBagLayout gridbag = new GridBagLayout();
    pane.setLayout(gridbag);
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 1.0; // Make column as wide as possible.
    JTextField textField = new JTextField("A TextField");
    textField.setMargin(new Insets(0, 2, 0, 2));
    textField.addFocusListener(this);
    gridbag.setConstraints(textField, c);
    add(textField);
    c.weightx = 0.1; // Widen every other column a bit, when possible.
    c.fill = GridBagConstraints.NONE;
    JLabel label = new JLabel("A Label");
    label.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
    label.addFocusListener(this);
    gridbag.setConstraints(label, c);
    add(label);
    String comboPrefix = "ComboBox Item #";
    final int numItems = 15;
    Vector<String> vector = new Vector<String>(numItems);
    for (int i = 0; i < numItems; i++) {
      vector.addElement(comboPrefix + i);
    }
    JComboBox comboBox = new JComboBox(vector);
    comboBox.addFocusListener(this);
    gridbag.setConstraints(comboBox, c);
    add(comboBox);
    c.gridwidth = GridBagConstraints.REMAINDER;
    JButton button = new JButton("A Button");
    button.addFocusListener(this);
    gridbag.setConstraints(button, c);
    add(button);
    c.weightx = 0.0;
    c.weighty = 0.1;
    c.fill = GridBagConstraints.BOTH;
    String listPrefix = "List Item #";
    Vector<String> listVector = new Vector<String>(numItems);
    for (int i = 0; i < numItems; i++) {
      listVector.addElement(listPrefix + i);
    }
    JList list = new JList(listVector);
    list.setSelectedIndex(1); // It"s easier to see the focus change
    // if an item is selected.
    list.addFocusListener(this);
    JScrollPane listScrollPane = new JScrollPane(list);
    gridbag.setConstraints(listScrollPane, c);
    add(listScrollPane);
    c.weighty = 1.0; // Make this row as tall as possible.
    c.gridheight = GridBagConstraints.REMAINDER;
    // Set up the area that reports focus-gained and focus-lost events.
    display = new JTextArea();
    display.setEditable(false);
    // The setRequestFocusEnabled method prevents a
    // component from being clickable, but it can still
    // get the focus through the keyboard - this ensures
    // user accessibility.
    display.setRequestFocusEnabled(false);
    display.addFocusListener(this);
    JScrollPane displayScrollPane = new JScrollPane(display);
    gridbag.setConstraints(displayScrollPane, c);
    add(displayScrollPane);
    setPreferredSize(new Dimension(450, 450));
    ((JPanel) pane).setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }
  public void focusGained(FocusEvent e) {
    displayMessage("Focus gained", e);
  }
  public void focusLost(FocusEvent e) {
    displayMessage("Focus lost", e);
  }
  void displayMessage(String prefix, FocusEvent e) {
    display.append(prefix
        + (e.isTemporary() ? " (temporary):" : ":")
        + e.getComponent().getClass().getName()
        + "; Opposite component: "
        + (e.getOppositeComponent() != null ? e.getOppositeComponent()
            .getClass().getName() : "null") + newline);
    display.setCaretPosition(display.getDocument().getLength());
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event dispatch thread.
   */
  private static void createAndShowGUI() {
    // Create and set up the window.
    FocusEventDemo frame = new FocusEventDemo("FocusEventDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // Set up the content pane.
    frame.addComponentsToPane(frame.getContentPane());
    // Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    /* Use an appropriate Look and Feel */
    try {
      // UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
      UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
    } catch (UnsupportedLookAndFeelException ex) {
      ex.printStackTrace();
    } catch (IllegalAccessException ex) {
      ex.printStackTrace();
    } catch (InstantiationException ex) {
      ex.printStackTrace();
    } catch (ClassNotFoundException ex) {
      ex.printStackTrace();
    }
    /* Turn off metal"s use of bold fonts */
    UIManager.put("swing.boldMetal", Boolean.FALSE);
    // Schedule a job for the event dispatch thread:
    // creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}





How to Write a Focus Listener

Focus events are fired whenever a component gains or loses the keyboard focus.



import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class UsingFocusListener {
  public static void main(String[] a) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextField textField = new JTextField("A TextField");
    textField.addFocusListener(new FocusListener() {
      public void focusGained(FocusEvent e) {
        displayMessage("Focus gained", e);
      }
      public void focusLost(FocusEvent e) {
        displayMessage("Focus lost", e);
      }
      void displayMessage(String prefix, FocusEvent e) {
        System.out.println(prefix
            + (e.isTemporary() ? " (temporary):" : ":")
            + e.getComponent().getClass().getName()
            + "; Opposite component: "
            + (e.getOppositeComponent() != null ? e.getOppositeComponent().getClass().getName()
                : "null"));
      }
    });
    frame.add(textField,"North");
    frame.add(new JTextField(),"South");
    frame.setSize(300, 200);
    frame.setVisible(true);
  }
}





The event IDs defined in the FocusEvent class

  1. FOCUS_GAINED
  2. FOCUS_LOST


The FocusListener Interface: respond to a component gaining or losing the focus

Defined MethodsDescriptionfocusGained(FocusEvent e)Called when a component gains the keyboard focusfocusLost(FocusEvent e)Called when a component loses the keyboard focus


Use Focus Events in Swing

import java.awt.Dimension;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class Main extends JPanel implements FocusListener {
  public Main() {
    JTextField textField = new JTextField("A TextField");
    textField.addFocusListener(this);
    JLabel label = new JLabel("A Label");
    label.addFocusListener(this);
    add(label);
    String comboPrefix = "ComboBox Item #";
    final int numItems = 15;
    Vector vector = new Vector(numItems);
    for (int i = 0; i < numItems; i++) {
      vector.addElement(comboPrefix + i);
    }
    JComboBox comboBox = new JComboBox(vector);
    comboBox.addFocusListener(this);
    add(comboBox);
    JButton button = new JButton("A Button");
    button.addFocusListener(this);
    add(button);
    String listPrefix = "List Item #";
    Vector listVector = new Vector(numItems);
    for (int i = 0; i < numItems; i++) {
      listVector.addElement(listPrefix + i);
    }
    JList list = new JList(listVector);
    list.setSelectedIndex(1); 
    list.addFocusListener(this);
    JScrollPane listScrollPane = new JScrollPane(list);
    listScrollPane.getVerticalScrollBar().setFocusable(false);
    listScrollPane.getHorizontalScrollBar().setFocusable(false);
    add(listScrollPane);
    setPreferredSize(new Dimension(450, 450));
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }
  void displayMessage(String prefix, FocusEvent e) {
    System.out.println(prefix
        + (e.isTemporary() ? " (temporary):" : ":")
        + e.getComponent().getClass().getName()
        + "; Opposite component: "
        + (e.getOppositeComponent() != null ? e.getOppositeComponent().getClass().getName()
            : "null") );
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("FocusEventDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JComponent newContentPane = new Main();
    newContentPane.setOpaque(true); // content panes must be opaque
    frame.setContentPane(newContentPane);
    frame.pack();
    frame.setVisible(true);
  }
  public void focusGained(FocusEvent e) {
    displayMessage("Focus gained", e);
}
public void focusLost(FocusEvent e) {
    displayMessage("Focus lost", e);
}
}





Validate a value on the lostFocus event

import java.awt.BorderLayout;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Main {
  public static void main(String[] a) {
    final JTextField textField = new JTextField(5);
 
    textField.addFocusListener(new FocusListener() {
      public void focusGained(FocusEvent e) {
      }
      public void focusLost(FocusEvent e) {
        if (!e.isTemporary()) {
          String content = textField.getText();
          if (!content.equals("a") ) {
            System.out.println("illegal value! " + content);
            SwingUtilities.invokeLater(new FocusGrabber(textField));
          }
        }
      }
    });
    JFrame frame = new JFrame();
    frame.add(textField,BorderLayout.CENTER);
    frame.setSize(300,300);
    frame.setVisible(true);
  
  
  }
}
class FocusGrabber implements Runnable {
  private JComponent component;
  public FocusGrabber(JComponent component) {
    this.ruponent = component;
  }
  public void run() {
    component.grabFocus();
  }
}





Validating a JTextField When Permanently Losing the Focus

import java.awt.FlowLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTextField component = new JTextField(10);
    JTextField component1 = new JTextField(10);
    component.addFocusListener(new MyFocusListener());
    component1.addFocusListener(new MyFocusListener());
    JFrame f = new JFrame();
    f.setLayout(new FlowLayout());
    f.add(component1);
    f.add(component);
    f.pack();
    f.setVisible(true);
  }
}
class MyFocusListener extends FocusAdapter {
  boolean showingDialog = false;
  public void focusGained(FocusEvent evt) {
    final JTextComponent c = (JTextComponent) evt.getSource();
    String s = c.getText();
    for (int i = 0; i < s.length(); i++) {
      if (!Character.isDigit(s.charAt(i))) {
        c.setSelectionStart(i);
        c.setSelectionEnd(i);
        break;
      }
    }
  }
  public void focusLost(FocusEvent evt) {
    final JTextComponent c = (JTextComponent) evt.getSource();
    String s = c.getText();
    if (evt.isTemporary()) {
      return;
    }
    for (int i = 0; i < s.length(); i++) {
      if (!Character.isDigit(s.charAt(i))) {
        System.out.println("must only contain digits");
        c.requestFocus();
        break;
      }
    }
  }
}