按照JTextField的方式使用JSpinner

时间:2008-12-18 23:19:36

标签: java swing jtextfield listeners jspinner

首先,为了让我的工作更容易解释,这里是我的一些代码:

JSpinner spin = new JSpinner();
JFormattedTextField text = getTextField(spin);

text.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
            // Do stuff...
    }
});

...

private JFormattedTextField getTextField(JSpinner spinner) {
    JComponent editor = spinner.getEditor();

    if (editor instanceof JSpinner.DefaultEditor) {
        return ((JSpinner.DefaultEditor )editor).getTextField();
    } else {
        System.err.println( "Unexpected editor type: "
                           + spinner.getEditor().getClass()
                           + " isn't a descendant of DefaultEditor" );
        return null;
    }
}

你可以看到,我走得那么远。事实上,当我在微调器(JFormattedTextField)的文本字段组件中键入一个值,然后按ENTER键时,它就可以工作。

我现在想要的是能够让文本字段响应ENTER,而不必手动输入新值(这种类型使得微调器的目的无法实现)。我该怎么做?

2 个答案:

答案 0 :(得分:4)

我知道这不是动作听众......但也许这对你有用吗?


    text.addKeyListener( new KeyAdapter() {
            @Override
            public void keyReleased( final KeyEvent e ) {
                if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
                    System.out.println( "enter pressed" );
                }
            }
        } );

答案 1 :(得分:1)

我刚刚遇到了与此相关的问题。在我的例子中,我有一个SpinnerNumberModel设置的JSpinner,所以我可以输入数字ID值,然后从远程数据库中检索它们。使用JButton作为查询的触发器,这一切都很顺利,但是我希望能够通过Tab将焦点切换到字段,并按Enter键,并且还可以通过输入带数字键的ID来更改值,然后按回车。

给我提出最多问题的是用数字键手动输入ID,然后按回车键。当我这样做时,查询仍然会发生,但它查询的是先前的ID而不是我刚输入的ID,所以我必须再次按Enter键来查询新ID(参见代码)

((JSpinner.DefaultEditor) minRng.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            queryData();
        }
    }
});

和查询方法:

private void queryData() {
    int minVal = Integer.parseInt(minRng.getValue().toString());
    queryDataBase(minVal);
}

为了解决这个问题,我所要做的就是强制查询等待运行直到微调器更新其值,这很容易通过使用SwingUtilities.invokeLater()强制它到EDT队列的末尾来完成,像这样:

((JSpinner.DefaultEditor) minRng.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    queryData();
                }
            });
        }
    }
});

由于invokeLater()现在在新值而不是前一个值上进行查询,当按下回车时,因为JSpinner已将其值更新为新输入的值。

我假设这样做的原因是输入的值不会正式应用于JSpinner,直到您按Enter键,这也会触发查询的键侦听器。自定义[query]键侦听器的KeyEvent似乎是队列中的第一个,因此它首先运行其代码,然后KeyEvent将值应用于JSpinner来自内部JFormattedTextField,这就是它查询旧值的原因。 SwingUtilities.invokeLater()只是将查询本身放在队列的末尾,因此它允许另一个KeyEvent在运行查询之前完成其代码。

修改

实现此目的的另一种方法是直接从JFormattedTextField而不是JSpinner请求值,因为这也应该返回新输入的值,因为JFormattedTextField包含您的值输入,但它还没有被传递给JSpinner,这似乎是问题所在。

private void queryData() {
    JFormattedTextField tf = ((JSpinner.DefaultEditor) minRng.getEditor()).getTextField();
    int minVal = Integer.parseInt(tf.getText());
    queryDataBase(minVal);
}

此方法的唯一问题是,在解析值时必须捕获任何NumberFormatException,其中SwingUtilities.invokeLater()方法允许微调器模型自动删除任何无效字符,并且继续查询。

无论如何,我对Java仍然缺乏经验,所以如果我对此的理解不正确,请在评论中告诉我。