我使用JSpinner
使用SpinnerNumberModel
使用double
值的GUI。
当我更改Editor
的{{1}}的内容时,我希望背景更改为黄色(以显示当前显示的值不是“已保存”的值JSpinner
分别为JSpinner
。
如果该内容无效(例如,超出我的Model
指定的允许范围或文字为“abc”),则背景应更改为红色。
我试图通过SpinnerNumberModel
实现我想要的但尚未成功,我也不确定它是否能够正常工作,因为我需要检查聚焦和散焦之间的内容。< / p>
我查看了FocusListener
组件存在的所有Listeners
的教程,但找不到适合该作业的正确教程。 (here I informed myself)
我是Swing
概念的新手,非常感谢能让我更接近解决问题的任何帮助,同时也帮助我们更好地理解Listeners
以及如何更好地使用它们! / p>
我的真正基本代码示例,提到使用焦点监听器的不良尝试:
Listeners
答案 0 :(得分:2)
JSpinner使用文本字段作为微调器的编辑器
因此,您可以将DocumentListener
添加到用作编辑器的文本字段的Document
。
类似的东西:
JTextField textField = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField());
textField.getDocument.addDocumentListener(...);
然后,当添加/删除文本时,将生成DocumentEvent,您可以进行错误检查。阅读Listener For Changes on a Document上Swing教程中的部分,了解更多信息和工作示例。
答案 1 :(得分:1)
您可以使用CaretListener
,这是一个开始:
import java.awt.Color;
import java.awt.Component;
import javax.swing.BoxLayout;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class SpinerTest{
JSpinner spinner;
public SpinerTest() {
JFrame frame = new JFrame("frame");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
SpinnerNumberModel model = new SpinnerNumberModel(0., 0., 100., 0.1);
spinner = new JSpinner(model);
setCaretListener();
frame.getContentPane().add(spinner);
frame.pack();
frame.setVisible(true);
}
private void setCaretListener() {
for(Component c : spinner.getEditor().getComponents()) {
JFormattedTextField field =(JFormattedTextField) c;
field.addCaretListener(new CaretListener(){
@Override
public void caretUpdate(CaretEvent ce) {
if (field.isEditValid()) {
//add aditional test as needed
System.out.println("valid Edit Entered " + field.getText());
field.setBackground(Color.WHITE);
}
else {
System.out.println("Invalid Edit Entered" + field.getText());
field.setBackground(Color.PINK);
}
}
});
}
}
public static void main(String[] args) {
new SpinerTest();
}
}
答案 2 :(得分:0)
我能够通过KeyListener
,DocumentListener
和FocusListener
的组合来完成任务。解决方案可能不是最简单的,但最后我编码了。这样可行。附加文件中的注释应该解释我是如何处理这个问题的。
我使用CommaReplacingNumericDocumentFilter expands DocumentFilter
class
扩展了原始任务,这不是我写的,我从教授那里得到了代码并仅根据我的需要进行了编辑。现在只有数字,减去和 e , E 被接受为JSpinner
中的条目。
逗号 替换 dot 。
<强>代码:强>
import java.awt.*;
import java.awt.event.*;
import java.util.Locale;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class test implements DocumentListener, ChangeListener, KeyListener{
boolean keyPressed;
JFrame frame;
SpinnerNumberModel model;
JSpinner spinner;
JComponent comp;
JFormattedTextField field;
public test() {
JFrame frame = new JFrame("frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
model = new SpinnerNumberModel(0., 0., 100000., .1);
spinner = new JSpinner(model);
//disable grouping for spinner
JSpinner.NumberEditor editor = new JSpinner.NumberEditor(spinner);
editor.getFormat().setGroupingUsed(false);
spinner.setEditor(editor);
comp = spinner.getEditor();
field = (JFormattedTextField) comp.getComponent(0);
field.getDocument().addDocumentListener(this);
field.addKeyListener(this);
spinner.addChangeListener(this);
frame.getContentPane().add(spinner);
frame.pack();
frame.setVisible(true);
}
@Override
public void insertUpdate(DocumentEvent e) {
DocumentEventHandler(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
DocumentEventHandler(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
DocumentEventHandler(e);
}
public static boolean isNumeric(String str)
{
try
{
double d = Double.parseDouble(str);
}
catch(NumberFormatException nfe)
{
return false;
}
return true;
}
public static void main(String[] args) {
//to get the right format for double precision numbers
Locale.setDefault(Locale.US);
test test = new test();
}
@Override
public void stateChanged(ChangeEvent e) {
System.out.println("valuechanged: " + spinner.getValue().toString());
if(keyPressed) {
field.setBackground(Color.WHITE);
}
keyPressed = false;
}
public void DocumentEventHandler(DocumentEvent e) {
//as soon as update is inserted, set background to yellow
if (keyPressed) {
field.setBackground(Color.YELLOW);
//check if input is numeric and in bounds
String text = field.getText();
if (isNumeric(text)) {
double value = Double.parseDouble(text);
if (value < (Double)model.getMinimum() || value > (Double)model.getMaximum()) {
field.setBackground(Color.RED);
}
}
else { //set background to red
field.setBackground(Color.RED);
}
}
keyPressed = false;
//System.out.println(e.toString());
//System.out.println("Text: " + field.getText());
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
/** If not done yet, replaces the DocumentFilter with one replacing commas by decimal points.
* This can't be done at the very beginning because the DocumentFilter would be changed to a
* javax.swing.text.DefaultFormatter$DefaultDocumentFilter when setting up the JSpinner GUI. */
public void keyPressed(KeyEvent e) {
PlainDocument document = (PlainDocument)(field.getDocument());
if(!(document.getDocumentFilter() instanceof CommaReplacingNumericDocumentFilter))
document.setDocumentFilter(new CommaReplacingNumericDocumentFilter());
/*Tell the other handlers that a key has been pressed and the change in the document does
* not come from using the JSpinner buttons or the MouseWheel.
*/
keyPressed = true;
}
}
/** A javax.swing.text.DocumentFilter that replaces commas to decimal points
* and ignores non-numeric characters except 'e' and 'E'. This is called before
* modi */
class CommaReplacingNumericDocumentFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr)
throws BadLocationException {
text = filter(text);
if (text.length() > 0)
super.insertString(fb, offset, text, attr);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attrs) throws BadLocationException {
text = filter(text);
if (text.length() > 0)
super.replace(fb, offset, length, text, attrs);
}
String filter(String text) {
return text.replace(',', '.').replaceAll("[^0-9eE.-]","");
}
}