2017-07-02 106 views
1

我有一个JSpinner使用SpinnerNumberModel使用double值的GUI。如何根据当前编辑的字段内容更改JSpinner的背景颜色?

只要我改变JSpinnerEditor的内容,我希望背景更改为黄色(表明当前显示的值不是“保存”分别在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); 
      } 
} 
} 
+0

1)为了更好地帮助越早,张贴[MCVE]或[简要,独立的,正确的示例](http://www.sscce.org/)。 2)请参阅[检测/修复代码块的悬挂紧密支架](http://meta.stackexchange.com/q/251795/155831),以解决问题,我不再担心修复问题。 3)为什么不改变微调框的边框颜色,或者它旁边图标的颜色?我总是小心地改变使用颜色出于各自原因的组件的BG颜色。 –

+0

感谢fb,我会尽快为自己找到一个解决方案来修复代码示例,并且已经修复了悬挂支架! 这样的东西肯定会让你这样的经验丰富的用户感到厌烦,但对于像我这样的新手来说肯定是个大陷阱;) – Vito

回答

0

我能够用KeyListener,一个DocumentListenerFocusListener的组合来完成任务。解决方案可能不是最简单的,但最后我编码了。这样可行。附加文件中的注释应解释我如何处理该问题。

我扩展了原来的任务,并且不是由我写的CommaReplacingNumericDocumentFilter expands DocumentFilterclass,我从我的教授处获得了代码,并将其编辑为仅适用于我的需要。现在只有数字减去ēē被接受为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.-]",""); 
} 
} 
2

一个JSpinner的使用文本字段的编辑器微调

所以,你可以添加DocumentListener到用作编辑器的文本字段的Document

喜欢的东西:

JTextField textField = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField()); 
textField.getDocument.addDocumentListener(...); 

然后添加文本时/移除的DocumentEvent会产生,你可以做你的错误检查。请参阅Listener For Changes on a Document的Swing教程中的部分以获取更多信息和工作示例。

+0

感谢您的帮助,下面的链接提供的示例显示了如何获取源文件,插入的字符数和字符总数。由于我需要解释插入的文本,如果您可以提供一个简短的示例,例如如何在字符串中插入元素,它将对我有所帮助。 看来我不得不使用Document事件方法的'getChange(Elemente elem)'方法,但是我发现它很混乱,我发现这里的例子(http://www.programcreek.com/java- api-examples/index.php?api = javax.swing.event.DocumentEvent.ElementChange)也没有帮助我。 – Vito

+0

@Vito,那么你的最终需求是改变文本字段的背景颜色,所以你必须有一个对文本字段的引用。然后,您可以使用getText()方法来获取文本并进行验证。或者您也可以从文档中获取文本。 – camickr

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(); 
    } 
} 
相关问题