2

JTextField が KeyListener からのものであるのに、setText("") メソッドを使用しても JTextField が単に「クリア」されないように見えるのはなぜでしょうか。これは ActionListener から正常に動作しますが、最も驚くべきことに、KeyListener メソッドがダミーのアクション イベント (単純なテストとしてその場で作成) を使用して ActionListener メソッドを呼び出そうとすると、入力されたテキストはそのまま残ります。

つまり、コマンド ラインから実行するときに、たとえばフィールドに「3」と入力すると、予想どおり、setText("test") メソッドが 3 を消去しないことがわかります。と欲望しますが、むしろそれをそのままにしておきます。ディスプレイに「test3」が表示されます。この行にコメントを付けました。JButton をクリックすると、テキストが適切に消去されます。JButton と JLabel はテキストを適切に変更します。しかし、JTextField はそうしません。次にボタンを押すと、アクション イベントが JTextField を適切にクリアすることがわかります。ここで、コメントアウトされた行を切り替えると、KeyTyped メソッドから actionPerformed メソッドを呼び出そうとしていることがわかります!!! それでも、テキスト フィールドに「3」を入力しても、それは消去されません。setText("") メソッドがそれをクリアすることを期待しますが、それはしません。これは、keyTyped() メソッドが JTextButton と同じ actionPerformed() メソッドを呼び出している場合でも同様です。

ここでの動機は少し役立つかもしれません。「クリア」ボタンを押したかのように、タイプされた瞬間に JTextField をクリアする特定のホットキーをトラップする必要があります。そして、これはうまくいかないようです。

私はこれまで Swing をあまり使ったことがありませんでしたが、これは非常に不可解です。

私のSSCCEコードは次のとおりです。

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

class P2 implements KeyListener, ActionListener
{
  JTextField fld;
  JButton btn;
  JLabel  lbl;

  P2()
  {
    JFrame frm = new JFrame("Test");
           fld = new JTextField(10);
    JPanel pnl = new JPanel();
           btn = new JButton("Clear it out");
           lbl = new JLabel("This is a test");

    fld.addKeyListener(this);

    btn.addActionListener(this);

    frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frm.setSize(400,400);
    frm.setLayout(new FlowLayout() );
    pnl.add(fld);
    pnl.add(btn);
    pnl.add(lbl);
    frm.getContentPane().add(pnl);
    frm.setVisible(true);
  }
  public void keyPressed(KeyEvent ke) {}
  public void keyReleased(KeyEvent ke) {}
  public void keyTyped(KeyEvent ke)
  {
     System.out.println("got a pressed key");

//this is the setText method that ought to wipe clean the field comments:
    this.fld.setText("test");
    this.btn.setText("try again");
    this.lbl.setText("got a presseed key");


//toggle this comment to see the invocation of the action event:
//    this.actionPerformed(new ActionEvent( new Object(), 2, "test")  );

  }
  public void actionPerformed(ActionEvent ae)
  {
     fld.setText("");
     fld.selectAll();
  }
  public static void main(String[] args)
  {
    SwingUtilities.invokeLater
    (
      new Runnable()
      {
        public void run()
        {
          new P2();
        }
      }
    );
  }
}
4

2 に答える 2

2

この動作は、が起動KeyEventされた後にフィールドによって処理されるという事実によるものです。KeyListener経由でイベントを消費することで回避できます

ke.consume();

あなたのメソッドの中にkeyTyped

要件に応じてSwingUtilities.invokeLater、現在のイベントの後に処理されるクリア呼び出しを 内にカプセル化し、更新後にフィールドをクリアする別の方法があります。

于 2011-09-23T06:37:38.260 に答える
2

フィールドのアクション マップに既に登録されているアクションを使用するように実装された、キー バインドを使用して「a」を押すとすべてのテキストを消去するコード スニペットを次に示します (ハワードが既に提案したように、コードを SwingUtilities.invokeLater にラップする必要があることに注意してください)。フィールドの内部処理に処理されることを保証します)

    JTextField normal = new JTextField("just a normal field", 10);
    final Action selectAll = normal.getActionMap().get("select-all");
    final Action cut = normal.getActionMap().get("cut-to-clipboard");
    Action combine = new AbstractAction() {

        @Override
        public void actionPerformed(final ActionEvent e) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    selectAll.actionPerformed(e);
                    cut.actionPerformed(e);

                }
            });
        }

    };
    normal.getActionMap().put("magic-delete-all", combine);
    normal.getInputMap().put(KeyStroke.getKeyStroke("A"), "magic-delete-all");
于 2011-09-23T07:56:49.960 に答える