JavaSwing_8.1:焦点事件及其监听器 - FocusEvent、FocusListener

简介: JavaSwing_8.1:焦点事件及其监听器 - FocusEvent、FocusListener

0 FocusEvent

image.png

低级别事件指示Component已获得或失去输入焦点。 由组件生成此低级别事件(如一个TextField)。 该事件被传递给每一个FocusListener或FocusAdapter注册,以接收使用组件的此类事件对象addFocusListener方法。 ( FocusAdapter对象实现FocusListener接口。)每个此类侦听器对象获取此FocusEvent当事件发生时。

有两个焦点事件级别:持久性和暂时性的。 永久焦点改变事件发生时焦点直接移动从一个组件到另一个,例如通过到requestFocus的(呼叫)或作为用户使用TAB键遍历组件。 当暂时丢失焦点的组件的另一个操作,比如释放Window或拖动滚动条的间接结果一时焦点变化的事件发生。 在这种情况下,原来的聚焦状态将被自动一旦操作完成恢复,或者,对于窗口失活的情况下,当窗口被重新激活。 永久和临时焦点事件使用FOCUS_GAINED和FOCUS_LOST事件id传递; 水平可以使用isTemporary()方法的事件区分开来。

如果未指定的行为将导致的id任何特定的参数FocusEvent实例不是从范围FOCUS_FIRST到FOCUS_LAST

1 FocusListener

用于在组件上接收键盘焦点事件的侦听器接口。 对处理焦点事件感兴趣的类

要么实现此接口(以及它包含的所有方法)

要么扩展抽象FocusAdapter类(仅覆盖感兴趣的方法)

然后,使用组件的addFocusListener方法向组件注册从该类创建的侦听器对象。 当组件获得或失去键盘焦点时,将调用侦听器对象中的相关方法,并将FocusEvent传递给它。

API

  • focusGained
  • image.png
  • focusLost
  • image.png

2 FocusAdapter

image.png

用于接收键盘焦点事件的抽象适配器类。

此类中的方法为空。

此类存在的目的是方便创建监听器对象。


继承此类来创建 FocusEvent 监听器,并针对感兴趣的事件重写方法。(如果你实现 FocusListener 接口,则必须定义该接口中的所有方法。此抽象类将所有这些方法都定义为 null,所以你只需针对所关心的事件重写方法即可)。


使用扩展的类创建一个侦听器对象,然后使用组件的 addFocusListener 方法向组件注册该监听器。当组件获得或失去键盘焦点时,可调用侦听器对象中的相关方法,并将 FocusEvent 传递给它。

API

  • focusGained
  • image.png
  • focusLost
  • image.png

3 如何编写焦点侦听器

每当组件获得或失去键盘焦点时,就会触发焦点事件。无论是通过鼠标,键盘还是以编程方式发生焦点变化,都是如此。要熟悉基本焦点概念或获取有关焦点的详细信息,请参阅如何使用焦点子系统。


本节说明如何通过在特定组件上注册FocusListener实例来获取焦点事件。

要仅获得窗口焦点,请改为实现WindowFocusListener实例。

要获取许多组件的焦点状态,请考虑在KeyboardFocusManager类上实现PropertyChangeListener实例,如如何使用焦点子系统中的将焦点更改跟踪到多个组件中所述。


下面的示例演示焦点事件。该窗口显示各种组件。注册在每个组件上的焦点侦听器报告每个焦点获得和焦点丢失的事件。对于每个事件,将报告焦点更改中涉及的其他组件,即相反的组件。

例如,当焦点从按钮转到文本字段时,按钮会触发焦点丢失事件(文本字段为相反的组件),然后文本字段会触发焦点获取事件(带有按钮作为相反的组件)。失去焦点以及获得焦点的事件可能是暂时的。例如,当窗口失去焦点时,会发生一个临时的焦点丢失事件。临时获得焦点的事件发生在弹出菜单上。

image.png

package events;
/*
 * FocusEventDemo.java
 *
 */
import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
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();
            }
        });
    }
}

单击启动按钮运行FocusEventDemo。

您将在文本区域中看到一条“焦点已获得:JTextField”消息-其“相反组件”为空,因为它是第一个具有焦点的组件。

单击标签。什么也没发生,因为默认情况下标签无法获得焦点。

单击组合框。焦点丢失事件由文本字段触发,焦点获得事件由组合框触发。现在,组合框显示它具有焦点,也许在文本周围有一条虚线-确切地表示方式取决于外观。

请注意,当焦点从一个组件更改为另一个组件时,第一个组件将触发焦点丢失事件,第二个组件将触发焦点获得事件。

从组合框的菜单中选择一个选项。再次单击组合框。请注意,没有报告焦点事件。只要用户操作相同的组件,焦点就会停留在该组件上。

单击打印焦点事件的文本区域。什么也没有发生,因为使用setRequestFocusEnabled(false)使文本区域不可点击。

单击文本字段以将焦点返回到初始组件。

按键盘上的Tab。焦点移到组合框,并跳过标签。

再次按Tab键。焦点移至按钮。

单击另一个窗口,以便FocusEventDemo窗口失去焦点。为按钮生成一个临时的焦点丢失事件。

单击FocusEventDemo窗口的顶部。该按钮触发了聚焦事件。

按键盘上的Tab。焦点移至列表。

再次按Tab键。焦点移到文本区域。

请注意,即使不允许您单击文本区域,也可以将其切换到该区域。这样一来,使用辅助技术的用户就可以确定组件在那里及其包含的内容。该演示通过在文本区域上调用setRequestFocusEnabled(false)来禁用文本区域的单击焦点,同时保留其选项卡焦点功能。该演示可以使用setFocusable(false)从焦点循环中真正删除该文本区域,但这将产生不幸的后果,使使用辅助技术的人员无法使用该组件。

再次按Tab键。焦点从列表移回到文本字段。您刚刚完成了一个聚焦周期。


目录
相关文章
|
6月前
移动端click事件、touch事件、tap事件的区别
移动端click事件、touch事件、tap事件的区别
207 0
|
6月前
|
iOS开发 容器
在做动画的控件不触发手势事件问题及解决方案
在做动画的控件不触发手势事件问题及解决方案
36 0
|
6月前
|
C#
C# 禁止ComboBox滚动事件细谈
C# 禁止ComboBox滚动事件细谈
|
JavaScript 前端开发
史上最详细的DOM事件之拖动事件
史上最详细的DOM事件之拖动事件 上篇博客讲了DOM的剪贴板事件,这篇博客我们来讲一讲DOM的拖动(DragEvent)事件。 HTMl代码: &lt;img src=&quot;../../CSS/0421/car.jpg&quot; draggable=&quot;false&quot;&gt; 1 JS代码: var oImg=document.getElementsByTagName(&quot;img&quot;)[0]; // DragEvent 拖动事件 // ondrag 该事件在元素正在拖动时触发 oImg.ondrag=function(ev){ console
|
图形学
Unity碰撞事件和触发事件
大家在刚开始接触Unity的时候,一定要理解碰撞与触发
507 0
Unity碰撞事件和触发事件
SwiftUI—如何实现对视图显示和消失事件的监听
SwiftUI—如何实现对视图显示和消失事件的监听
688 0
SwiftUI—如何实现对视图显示和消失事件的监听
|
Windows
WindowFocusListener窗体焦点监听器
WindowFocusListener窗体焦点监听器
272 0
WindowFocusListener窗体焦点监听器
|
JavaScript C#
C#(WPF)去除事件中注册的事件处理方法!
在WPF中,移除一个事件中已经注册的处理方法,看似简单,实际还是很痛苦的一件事情。因为C#的灵活性,定义事件的方法也是多种多样。我自己定义了一个事件: public event EventHandler TestEvent; 当我想注销这个事件上注册的所有方法的时候,我可以按如下的方法进行 Delegate[] dels = TestEvent.
4013 0
|
.NET C# 开发框架
WPF的路由事件、冒泡事件、隧道事件(预览事件)
原文:WPF的路由事件、冒泡事件、隧道事件(预览事件) 本文摘要: 1:什么是路由事件; 2:中断事件路由; 3:自定义路由事件; 4:为什么需要自定义路由事件; 5:什么是冒泡事件和预览事件(隧道事件); 1:什么是路由事件     WPF中的事件为路由事件,所谓路由事件,MSDN定义如下:     功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。
1769 0