Swing中requestFocusInWindow()和grabFocus()之间的区别

Jav*_*cal 5 java swing focus

我想知道requestFocusInWindow()grabFocus()方法之间的区别.他们两个都很适合在这个程序中抓住我的焦点.因此,我无法理解其中的差异.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Focus extends JFrame
{
JButton jb;

    public Focus()
    {
        createAndShowGUI();
    }

    private void createAndShowGUI()
    {
        setTitle("grabFocus() vs requestFocusInWindow()");
        setLayout(new FlowLayout());
        setSize(400,400);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jb=new JButton("Open Dialog");
        jb.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ae)
            {
                showDialog();
            }
        });

        add(jb);
    }

    private void showDialog()
    {
        JDialog jd=new JDialog();
        jd.setLayout(new GridLayout(2,2));
        jd.setVisible(true);


        JLabel l1=new JLabel("Label 1");
        JLabel l2=new JLabel("Label 2");

        JTextField jt1=new JTextField(20);
        JTextField jt2=new JTextField(20);

        jd.add(l1);
        jd.add(jt1);
        jd.add(l2);
        jd.add(jt2);

        // Both of them are doing the thing
        //jt2.grabFocus();
        jt2.requestFocus();

        jd.pack();
    }

    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable(){
            public void run()
            {
                new Focus();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

Jav*_*cal 13

答案很简单,grabFocus() 抓住焦点,无论顶级祖先是否是焦点窗口.如果窗口未激活,则使其处于活动状态以使组件获得焦点.

然而,只有当它的顶级祖先是聚焦窗口时requestFocusInWindow(),才能获得调用它的组件的焦点.

在您的示例中,JDialog是顶级祖先,JButton单击时会自动获得焦点.所以requestFocusInWindow()grabFocus()没有什么区别.

我重写了程序,以便用务实的方法更好地理解差异.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Focus extends JFrame
{
JButton jb;
JTextField jt;

    public Focus()
    {
        createAndShowGUI();
    }

    private void createAndShowGUI()
    {
        setTitle("grabFocus() vs requestFocusInWindow()");
        setLayout(new FlowLayout());
        setSize(400,400);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jb=new JButton("Open Dialog");
        jb.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ae)
            {
                showDialog();
            }
        });

        add(jb);

        jt=new JTextField(20);

        add(jt);
    }

    private void showDialog()
    {
        JDialog jd=new JDialog();
        jd.setLayout(new GridLayout(2,2));
        jd.setVisible(true);


        JLabel l1=new JLabel("Label 1");
        JLabel l2=new JLabel("Label 2");

        JTextField jt1=new JTextField(20);
        JTextField jt2=new JTextField(20);

        jd.add(l1);
        jd.add(jt1);
        jd.add(l2);
        jd.add(jt2);

        jt.requestFocusInWindow();
        //jt.grabFocus();

        jd.pack();
    }

    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable(){
            public void run()
            {
                new Focus();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,requestFocusInWindow()叫上jt,它不工作(即jt未获得焦点),因为JDialog被激活的时候JButton被点击,并JTextFieldJDialog获得焦点.

接下来,grabFocus()工作.当JButton被点击时,JDialog显示出来,但不会被激活.因为调用后grabFocus(),立即JFrame成为活动的顶层祖先和jt强迫获取焦点.

  • 虽然你没有在你的这篇文章中提到真正的东西,但__grabFocus()不会被使用___.来自[Java Docs](http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#grabFocus())的一行,用于巩固声明 - __"此方法旨在实现供焦点实现使用.客户端代码不应该使用此方法;相反,它应该使用requestFocusInWindow()"__ -1因为:( (8认同)
  • 不同之处在于,程序员假设在应用程序代码中使用一个而不是另一个,而不是一个给出的效果,因为如 Java Docs 所述,该部分属于 Focus 实现。在我看来,首先发布这个问题是错误的,因为 Java Docs 明确指出在客户端代码中使用哪种方法。 (2认同)