如何根据当前编辑的字段内容更改JSpinner的背景颜色?
我有一个JSpinner
使用SpinnerNumberModel
使用double
值的GUI。如何根据当前编辑的字段内容更改JSpinner的背景颜色?
只要我改变JSpinner
的Editor
的内容,我希望背景更改为黄色(表明当前显示的值不是“保存”分别在JSpinner
之一的Model
。
如果该内容无效(如出由指定的允许范围内的我SpinnerNumberModel
或文本为“ABC”)的背景应更改为红色。
我想实现我想用一个FocusListener
既可但还没有成功,我也不确定它是否可以工作,因为我需要检查聚焦和散焦之间的内容。
我选中了所有Listeners
的教程,其中存在Swing
组件,但无法找到适合该作业的正确组件。 (here I informed myself)
我是新来的Listeners
概念,真的希望这让我更接近解决问题,还有助于任何帮助一般理解Listeners
以及如何在这种情况下更好地使用它们!
我很基本的代码与使用的焦点侦听器所提到的可怜尝试例如:
public class test implements FocusListener{
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., 100., 0.1);
spinner = new JSpinner(model);
comp = spinner.getEditor();
field = (JFormattedTextField) comp.getComponent(0);
field.addFocusListener(this);
frame.getContentPane().add(spinner);
frame.getContentPane().add(new JButton("defocus spinner")); //to have something to defocus when testing :)
frame.pack();
frame.setVisible(true);
}
@Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
//when the values of the field and the spinner don't match, the field should get yellow
if(!field.getValue().equals(spinner.getModel().getValue())) {
field.setBackground(Color.YELLOW);
}
}
@Override
public void focusLost(FocusEvent e) {
// TODO Auto-generated method stub
//if they match again, reset to white
if(!field.getValue().equals(spinner.getModel().getValue())) {
field.setBackground(Color.RED);
}
}
}
我能够用KeyListener
,一个DocumentListener
和FocusListener
的组合来完成任务。解决方案可能不是最简单的,但最后我编码了。这样可行。附加文件中的注释应解释我如何处理该问题。
我扩展了原来的任务,并且不是由我写的CommaReplacingNumericDocumentFilter expands DocumentFilter
class
,我从我的教授处获得了代码,并将其编辑为仅适用于我的需要。现在只有数字,减去和ē,ē被接受为JSpinner
条目。 逗号是取代与点也。
代码:
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.-]","");
}
}
一个JSpinner的使用文本字段的编辑器微调
所以,你可以添加DocumentListener
到用作编辑器的文本字段的Document
。
喜欢的东西:
JTextField textField = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField());
textField.getDocument.addDocumentListener(...);
然后添加文本时/移除的DocumentEvent会产生,你可以做你的错误检查。请参阅Listener For Changes on a Document的Swing教程中的部分以获取更多信息和工作示例。
感谢您的帮助,下面的链接提供的示例显示了如何获取源文件,插入的字符数和字符总数。由于我需要解释插入的文本,如果您可以提供一个简短的示例,例如如何在字符串中插入元素,它将对我有所帮助。 看来我不得不使用Document事件方法的'getChange(Elemente elem)'方法,但是我发现它很混乱,我发现这里的例子(http://www.programcreek.com/java- api-examples/index.php?api = javax.swing.event.DocumentEvent.ElementChange)也没有帮助我。 – Vito
@Vito,那么你的最终需求是改变文本字段的背景颜色,所以你必须有一个对文本字段的引用。然后,您可以使用getText()方法来获取文本并进行验证。或者您也可以从文档中获取文本。 – camickr
您可以使用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();
}
}
1)为了更好地帮助越早,张贴[MCVE]或[简要,独立的,正确的示例](http://www.sscce.org/)。 2)请参阅[检测/修复代码块的悬挂紧密支架](http://meta.stackexchange.com/q/251795/155831),以解决问题,我不再担心修复问题。 3)为什么不改变微调框的边框颜色,或者它旁边图标的颜色?我总是小心地改变使用颜色出于各自原因的组件的BG颜色。 –
感谢fb,我会尽快为自己找到一个解决方案来修复代码示例,并且已经修复了悬挂支架! 这样的东西肯定会让你这样的经验丰富的用户感到厌烦,但对于像我这样的新手来说肯定是个大陷阱;) – Vito