2017-07-02 107 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(); 
    } 
} 
相關問題