2

JFrame 内のフォーカスに関係なく、すべての を 1 つの特定の に再ディスパスするKeyboardFocusManager独自のカスタムをいじっています。これは、テキスト入力に関する限り魅力的に機能しますが、 a が再ディスパッチされたときに、がそのテキストを a に投稿することも望んでいます。何らかの理由で、これを行うことはできません。テキスト フィールドにカーソルを置いて ENTER を押すと発生する actionListener を設定しましたが、ENTER イベントが.KeyEventDispatcherKeyEventJTextFieldJTextFieldJTextAreaKeyEvent.VK_ENTERJTextFieldKeyboardFocusManager.redispatchEvent(keyEvent)

また、Enter キーが押された場合に、変更されていない KeyEvent ではなく ActionEvent を再ディスパスしようとしましたが、役に立ちませんでした :( ActionEvent をコンポーネントにディスパスすると、ActionListeners が起動すると思うかもしれませんが、違います。

誰かがこれがなぜなのか説明できますか? そして、それをうまく回避する方法を提案しますか?

SSCCE:

package viewlayer.guiutil.focus;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Runnable;import java.lang.String;
import java.util.Date;

public class Test extends JFrame
{
    private JTextField m_chatInput;
    private JTextArea m_textArea;

    public static void main(String... args)
    {
        Test test1 = new Test();
        test1.run(test1);
    }

    public void run(final Test test)
    {
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        test.setSize(250, 400);

        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new MyKeyEventDispatcher());

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                test.init();
            }
        });

        test.setVisible(true);
    }

    public void init()
    {
        JPanel panel = new JPanel (new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(2,5,1,1);
        gbc.weightx = 1.0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridwidth = GridBagConstraints.REMAINDER;

        JLabel chatLabel = new JLabel("Chat input field:");
        panel.add(chatLabel,gbc);

        m_chatInput = new JTextField(15);
        m_chatInput.setActionCommand(MyActionListener.ACTION_PERFORMED);
        m_chatInput.addActionListener(new MyActionListener());
        panel.add(m_chatInput,gbc);

        JTextField chatInput = new JTextField(15);
        panel.add(chatInput,gbc);

        JLabel text = new JLabel("chat history:");
        panel.add(text,gbc);

        m_textArea = new JTextArea(5, 15);
        m_textArea.setFocusable(false);
        panel.add(m_textArea,gbc);

        JButton postButton = new JButton("Post");
        postButton.setActionCommand(MyActionListener.ACTION_PERFORMED);
        postButton.addActionListener(new MyActionListener());
        panel.add(postButton,gbc);
        gbc.weighty = 1.0;
        gbc.anchor = gbc.NORTHWEST;

        setLayout(new FlowLayout(FlowLayout.LEFT));
        add(panel);
    }

    private class MyKeyEventDispatcher implements KeyEventDispatcher
    {
        public boolean dispatchKeyEvent(KeyEvent keyEvent)
        {
            KeyboardFocusManager.getCurrentKeyboardFocusManager().redispatchEvent(m_chatInput, keyEvent);

            return false;
        }
    }

    private class MyActionListener implements ActionListener
    {
        private static final String ACTION_PERFORMED = "ACTION_PERFORMED";

        public void actionPerformed(ActionEvent actionEvent)
        {
            if(actionEvent.getActionCommand().equals(ACTION_PERFORMED))
            {
                Date date = new Date(System.currentTimeMillis());
                m_textArea.append(date.getHours() +":"+ date.getMinutes() +":"+ date.getSeconds() + " - " + m_chatInput.getText() + "\n");
                m_chatInput.setText("");
            }
        }
    }
}
4

3 に答える 3

3

テキストフィールドコードには、リスナーコードを呼び出す前に、コンポーネントにフォーカスがあることを確認するためのテストがあります。

    public void actionPerformed(ActionEvent e) {
        JTextComponent target = getFocusedComponent();
        if (target instanceof JTextField) {
            JTextField field = (JTextField) target;
            field.postActionEvent();
        }
    }

ただし、KeyEventDispatcherから直接postActionEvent()メソッドを呼び出すことができるはずです。

if (enter key)
   m_chatInput.postActonEvent();
else
   // redispatch the event
于 2011-02-22T17:02:45.140 に答える
0

次の行を削除する必要があります。

m_chatInput.setFocusable(false);

そして境界線より上:

Date date = new Date(System.currentTimeMillis());

挿入する必要があります:

requestFocusInWindow(m_chatInput);

これがうまくいった場合、またはもう少し調整する必要がある場合は、投稿してください。

于 2011-02-22T13:46:32.447 に答える
0

chatInput に集中し続けるために使用できる回避策を見つけたと思います。

requestFocusInWindow(m_chatInput);
KeyboardFocusManager focusManager =
KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(
    new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent e) {
            String prop = e.getPropertyName();
            if ("focusOwner".equals(prop)) {
            requestFocusInWindow(m_chatInput);
            }
        }
    }
 );

次の場所にあるコードに基づいてこれを変更しました。

http://download.oracle.com/javase/tutorial/uiswing/misc/focus.html

于 2011-02-22T14:40:25.700 に答える