1. ホーム
  2. java

[解決済み] SwingのrequestFocusInWindow()とgrabFocus()の違いについて

2022-02-14 21:35:40

質問

との違いを教えてほしい。 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();
            }
        });
    }
}

解決方法は?

答えは簡単です。 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();
            }
        });
    }
}

ここです。 requestFocusInWindow() が呼び出されるのは jt となってうまくいかない(つまり jt がフォーカスを獲得しないためです。 JDialog がアクティブになったときに JButton がクリックされ JTextField の中に JDialog がフォーカスを得る。

次に grabFocus() が動作します。このとき JButton がクリックされる。 JDialog が表示されますが、アクティブにはなりません。なぜなら grabFocus() を実行すると、すぐに JFrame がアクティブなトップレベルの祖先となり jt 強制 にフォーカスが当たるようにします。