Java JSpinner 值更改事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3949382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JSpinner Value change Events
提问by user236501
How to make the update immediately when the jSpinner value was changed.
如何在 jSpinner 值更改时立即进行更新。
ChangeListener listener = new ChangeListener() {
public void stateChanged(ChangeEvent e) {
jLabel.setText(e.getSource());
}
};
spinner1.addChangeListener(listener);
The code above doesnt change the label text automatically, it required you to click again anyplace to update.
上面的代码不会自动更改标签文本,它需要您再次单击任何地方才能更新。
回答by trashgod
The code you show appears correct. For reference, here is a working example.
您显示的代码显示正确。作为参考,这里是一个工作示例。
Addendum: While the JSpinner
has focus, the left and right arrow keys move the caret. The up arrow increments and the down arrow decrements the field containing the caret. The change is (effectively) simultaneous in both the spinner and the label.
附录:当JSpinner
有焦点时,左右箭头键移动插入符号。向上箭头递增,向下箭头递减包含插入符号的字段。更改在微调器和标签中(有效地)同时发生。
To access the JFormattedTextField
of the JSpinner.DateEditor
, use the parent's getTextField()
method. A suitable caret listener or text input listener may then be used to update the label as desired.
要访问JFormattedTextField
的JSpinner.DateEditor
,用父母的getTextField()
方法。然后可以使用合适的插入符监听器或文本输入监听器来根据需要更新标签。
Addendum: Update to use setCommitsOnValidEdit
, as suggested here.
附录:更新使用setCommitsOnValidEdit
,如建议here。
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DateEditor;
import javax.swing.SpinnerDateModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.DefaultFormatter;
/**
* @see https://stackoverflow.com/questions/2010819
* @see https://stackoverflow.com/questions/3949518
*/
public class JSpinnerTest extends JPanel {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame("JSpinnerTest");
f.add(new JSpinnerTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
});
}
public JSpinnerTest() {
super(new GridLayout(0, 1));
final JLabel label = new JLabel();
final JSpinner spinner = new JSpinner();
Calendar calendar = Calendar.getInstance();
Date initDate = calendar.getTime();
calendar.add(Calendar.YEAR, -5);
Date earliestDate = calendar.getTime();
calendar.add(Calendar.YEAR, 10);
Date latestDate = calendar.getTime();
spinner.setModel(new SpinnerDateModel(
initDate, earliestDate, latestDate, Calendar.MONTH));
DateEditor editor = new JSpinner.DateEditor(spinner, "MMM yyyy");
spinner.setEditor(editor);
JFormattedTextField jtf = editor.getTextField();
DefaultFormatter formatter = (DefaultFormatter) jtf.getFormatter();
formatter.setCommitsOnValidEdit(true);
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
JSpinner s = (JSpinner) e.getSource();
label.setText(s.getValue().toString());
}
});
label.setText(initDate.toString());
this.add(spinner);
this.add(label);
}
}
回答by spuas
Problem here is that when you edit the JSpinner
value manually by typing from the keyboard, the stateChanged
event is not fired until the focus is lost by the JSpinner
or until Enter key has been pressed.
这里的问题是,当您JSpinner
通过从键盘输入手动编辑值时,stateChanged
事件不会被触发,直到焦点丢失JSpinner
或 直到按下 Enter 键。
If you want to upload the value, a KeyListener
is needed which will perform a setValue
in the JSpinner
for each typed key.
如果您想上传的值,KeyListener
则需要将执行一个setValue
在JSpinner
每个输入的密钥。
I leave an example here for a JSpinner
with a SpinnerNumberModel
:
我离开这里的例子为JSpinner
具有SpinnerNumberModel
:
JSpinner spinner= new JSpinner();
spinner.setModel(new SpinnerNumberModel(0, 0, Integer.MAX_VALUE, 1));
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
jLabel.setText(spinner.getValue());
}
});
final JTextField jtf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
jtf.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
String text = jtf.getText().replace(",", "");
int oldCaretPos = jtf.getCaretPosition();
try {
Integer newValue = Integer.valueOf(text);
spinner.setValue(newValue);
jtf.setCaretPosition(oldCaretPos);
} catch(NumberFormatException ex) {
//Not a number in text field -> do nothing
}
}
});
回答by kleopatra
The answer is to configure the formatter used in the JFormattedTextField which is a child of the spinner's editor:
答案是配置 JFormattedTextField 中使用的格式化程序,它是微调器编辑器的子项:
formatter.setCommitsOnValidEdit(true);
Unfortunately, getting one's hand on it is as long and dirty as the introductory sentence:
不幸的是,接触它就像介绍性句子一样冗长和肮脏:
final JSpinner spinner = new JSpinner();
JComponent comp = spinner.getEditor();
JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
formatter.setCommitsOnValidEdit(true);
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
LOG.info("value changed: " + spinner.getValue());
}
});
A slightly (but not by much) cleaner way might be to subclass NumberEditor and expose a method which allows the config
稍微(但不是很多)更简洁的方法可能是将 NumberEditor 子类化并公开一个允许配置的方法
回答by Isidore Bennett
I'm new so I might be breaking some rules and I might be late. But I found some of the answers a bit confusing so I played around in NetBeans IDE and found that if you right click on the jspinner GUI component placed on your jform and go to events-> change, code will be generated for you.
我是新来的,所以我可能会违反一些规则,我可能会迟到。但是我发现一些答案有点令人困惑,所以我在 NetBeans IDE 中进行了尝试,发现如果您右键单击放置在 jform 上的 jspinner GUI 组件并转到事件-> 更改,则会为您生成代码。
回答by rvit34
It might be an late answer but you may use my approach.
As spuasmentioned above the problem is that stateChanged
event is fired only when focus is lost or Enter key is pressed.
Using KeyListeners is not an good idea as well.
It would be better to use DocumentListener
instead. I modified spuas's example a bit and that's what I got:
这可能是一个迟到的答案,但您可以使用我的方法。
正如上面提到的,问题是stateChanged
只有在失去焦点或按下 Enter 键时才会触发事件。
使用 KeyListeners 也不是一个好主意。
用它DocumentListener
代替会更好。我稍微修改了 spuas 的例子,这就是我得到的:
JSpinner spinner= new JSpinner();
spinner.setModel(new SpinnerNumberModel(0, 0, Integer.MAX_VALUE, 1));
final JTextField jtf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
jtf.getDocument().addDocumentListener(new DocumentListener() {
private volatile int value = 0;
@Override
public void removeUpdate(DocumentEvent e) {
showChangedValue(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
showChangedValue(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
showChangedValue(e);
}
private void showChangedValue(DocumentEvent e){
try {
String text = e.getDocument().getText(0, e.getDocument().getLength());
if (text==null || text.isEmpty()) return;
int val = Integer.parseInt(text).getValue();
if (value!=val){
System.out.println(String.format("changed value: %d",val));
value = val;
}
} catch (BadLocationException | NumberFormatException e1) {
//handle if you want
}
}
});
回答by Stephen Cuminger
The last answer can be rearranged a little to make it a little more flexible. You can simply use this new MyJSpinner in place of any JSpinner. The biggest change is that you can use this new version with any underlying model of the JSpinner (int, double, byte, etc.)
最后一个答案可以稍微重新排列,使其更加灵活。您可以简单地使用这个新的 MyJSpinner 代替任何 JSpinner。最大的变化是您可以将这个新版本与 JSpinner 的任何底层模型(int、double、byte 等)一起使用。
public class MyJSpinner extends JSpinner{
boolean setvalueinprogress=false;
public MyJSpinner()
{
super();
final JTextField jtf = ((JSpinner.DefaultEditor) getEditor()).getTextField();
jtf.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
showChangedValue(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
showChangedValue(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
showChangedValue(e);
}
private void showChangedValue(DocumentEvent e){
try {
if (!setvalueinprogress)
MyJSpinner.this.commitEdit();
} catch (NumberFormatException | ParseException ex) {
//handle if you want
Exceptions.printStackTrace(ex);
}
}
});
}
@Override
public void setValue(Object value) {
setvalueinprogress=true;
super.setValue(value);
setvalueinprogress=false;
}
}