5

Swing プログラムを使用していますが、少し問題があります。プログラムには 2 つのウィンドウがあります (両方とも JFrames)。メイン ウィンドウは問題なく、この問題には関係ありません。

私が問題を抱えているウィンドウには、JPanel を含む JScrollPane が含まれており、JMenuBar があります。JPanel には、多数の JTextComponents (いくつかの JTextFields、いくつかの JTextAreas) があります。

私がやりたいことは、 JMenuItem にアタッチされた ActionListener に、フォーカスのある JTextComponent を見つけることです。

以前の投稿フォーカスされたコンポーネント リファレンスHow to find the object currently has focus を見てきました。私の問題は、特定のウィンドウのgetFocusOwner()メソッドを呼び出しても JFrame の が返されるだけでJRootPane、まったく役に立たないことです。isFocusable()問題の JScrollPane と JPanel はどちらも、メソッドに従ってフォーカス可能です。これは、メニュー項目をクリックする前に JTextComponents の 1 つに実際にテキストを入力した場合でも発生します。メニューなどを開いている間、カーソルはテキスト フィールドでまだ点滅します。価値があるのは、getMostRecentFocusOwner()単に JRootPane を返すことです。

4

4 に答える 4

2

TextActions を使用すると、アクションはどの JTextComponent にフォーカスがあるかを認識します。ここで見つけたいくつかのコードを変更して、TextActions が 1 つの JTextArea からのものであっても、フォーカスのあるすべてのテキスト コンポーネントで自動的に機能することを示しました。

import java.awt.GridLayout;
import javax.swing.*;

public class TextActionExample {
  public static void main(String[] args) {

    // Create a text area.
    JTextArea ta = new JTextArea(15, 30);
    ta.setLineWrap(true);

    // Add all actions to the menu (split into two menus to make it more
    // usable).
    Action[] actions = ta.getActions();
    JMenuBar menubar = new JMenuBar();
    JMenu actionmenu = new JMenu("Actions");
    menubar.add(actionmenu);

    JMenu firstHalf = new JMenu("1st Half");
    JMenu secondHalf = new JMenu("2nd Half");
    actionmenu.add(firstHalf);
    actionmenu.add(secondHalf);

    int mid = actions.length / 2;
    for (int i = 0; i < mid; i++) {
      firstHalf.add(actions[i]);
    }
    for (int i = mid; i < actions.length; i++) {
      secondHalf.add(actions[i]);
    }

    JTextField textField = new JTextField(20);
    JPanel textFieldPanel = new JPanel();
    textFieldPanel.add(textField);

    JPanel mainPanel = new JPanel(new GridLayout(1, 0, 5, 5));
    mainPanel.add(new JScrollPane(ta));
    mainPanel.add(new JScrollPane(new JTextArea(15, 30)));
    mainPanel.add(textFieldPanel);


    // Show it . . .
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(mainPanel);
    f.setJMenuBar(menubar);
    f.pack();
    f.setVisible(true);
  }
}

これは私がもっと学ばなければならない非常に興味深いものです。

于 2012-07-02T22:48:26.643 に答える
1

メニュー項目をクリックするとフォーカスが失われるため、これを解決したと思います。フォーカスがある人を確認する前に、フォーカスがコンポーネントに戻るのを待つ必要があります。スイングタイマーを使用してこれを行いましたこれは 100 ミリ秒待機してからそのメソッドを実行して、どのコンポーネントにフォーカスがあるかを確認します。

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.TimerTask;
import javax.swing.*;

public class JavaApplication180 extends JFrame {

    private JTextField[] JTextFields;
    private JMenuBar menuBar;
    private JMenu menu;
    private JMenuItem item;

    public JavaApplication180() {
        initComponents();

        createAndShowUI();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new JavaApplication180();
            }
        });
    }

    private void createAndShowUI() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setLayout(new GridLayout(2, 2, 10, 10));
        setJMenuBar(menuBar);
        addComponentsToPane();

        pack();
        setVisible(true);
    }

    private void initComponents() {
        JTextFields = new JTextField[4];

        menuBar = new JMenuBar();
        item = new JMenuItem("Who has focus?");
        item.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                TimerTask tt = new TimerTask() {

                    @Override
                    public void run() {
                        JOptionPane.showMessageDialog(null, getMostRecentFocusOwner().getName());
                    }
                };
                new java.util.Timer().schedule(tt, 100);
            }
        });

        menu = new JMenu("File");
        menu.add(item);
        menuBar.add(menu);
    }

    private void addComponentsToPane() {
        for (int i = 0; i < JTextFields.length; i++) {
            JTextFields[i] = new JTextField();
            JTextFields[i].setText(String.valueOf(i));
            JTextFields[i].setName(String.valueOf(i));
            getContentPane().add(JTextFields[i]);
        }
    }
}
于 2012-07-02T21:48:32.290 に答える
0

これが必要になったとき、私はフォーカスリスナーを書きました。JTextFieldsの2つの列を持つJPanelがあり、フォーカスリスナーはユーザーが最後に使用した列を追跡していました。ユーザーがボタンをクリックするだけで、最後にフォーカスされた列にテキストを入力できるようにしました。すべてのテキストフィールドにFocusListenerのインスタンスを1つだけ使用し、最後にフォーカスされたコンポーネントを参照するフィールドを作成します。次に、メニューアクションでそのフィールドをクエリして、使用するテキストフィールドを決定できます。

http://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.htmlを参照してください

于 2012-07-02T21:20:11.900 に答える