2016-01-12 9 views
1

У меня есть Jpanel с текстовым полем. Я использую documentListener для сохранения изменений, когда пользователь вводит текстовое поле. Пользователь может набирать между 1-1000, если он вводит что-либо еще, появится всплывающее окно с сообщением об ошибке. Теперь я использую invokeLater, но это вызывает бесконечный цикл, если пользователь вводит> 1000. Как я могу это исправить.documentlistener с invokelater идет бесконечный цикл

mMaxLabelLength = new JTextField(); 
mMaxLabelLength.getDocument().addDocumentListener(this); 
@Override 
public void changedUpdate(DocumentEvent arg0) 
{ 
} 

@Override 
public void insertUpdate(DocumentEvent arg0) 
{ 
    saveActions(); 
    mMaxLabelLength.requestFocus(); 

} 

@Override 
public void removeUpdate(DocumentEvent arg0) 
{ 
    saveActions(); 
    mMaxLabelLength.requestFocus(); 
} 
private boolean saveActions() 
{ 
    // get text 
    String strValue = mMaxLabelLength.getText(); 

    // validate: must be positive integer between 1-1000; 
    boolean bSaveIt = true; 
    try 
    { 
     int nValue = Integer.parseInt(strValue); 
     if (nValue < 1 || nValue > 1000) 
      bSaveIt = false; 
    } 
    catch (NumberFormatException ne) 
    { 
     bSaveIt = false; 
    } 

    // save data to properties if valid 
    if (bSaveIt) 
    { 
     //do something 
    } 
    else 
    { 
     // error message 
     JOptionPane.showMessageDialog(this, "Please enter an integer value between 1 and 1000.", "Invalid Entry", JOptionPane.INFORMATION_MESSAGE); 
       SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
            int nMaxLabel = getMaxPieLabel(); 
       mMaxLabelLength.setText(new Integer(nMaxLabel).toString()); 
      } 
     }); 
     return false; 
    } 
    setVisible(true); 
    return true; 
} 
+0

Кажется мне, что, когда вы звоните 'mMaxLabelLength.setText (...)', вы запуска 'insertUpdate' ... который называет' SetText () 'снова. – Brian

+0

Я понимаю (из моих журналов), mMaxLabelLength.setText (...) вызывает removeUpdate и insertUpdate одновременно, и именно поэтому он попадает в бесконечный цикл. Поскольку mMaxLabelLength.getText становится 0. – user1631306

+0

Он отлично работает с «invokeAndWait», но появляется сообщение об ошибке «Не удается вызвать invokeAndWait из потока диспетчера событий», когда он пытается установить vaue. – user1631306

ответ

3

Это на самом деле не область ответственности за DocumentListener изменить состояние Document или взаимодействовать с пользовательским интерфейсом.

Вместо этого, вы, вероятно, следует с помощью DocumentFilter, который позволит вам поймать недопустимое состояние до его фиксации на Document и уведомления пользовательских событий для оповещения заинтересованных сторон, которые имели место нарушения, например ...

import java.awt.EventQueue; 
import java.awt.GridBagLayout; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.EmptyBorder; 
import javax.swing.text.AbstractDocument; 
import javax.swing.text.AttributeSet; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.DocumentFilter; 

public class Example { 

    public static void main(String[] args) { 
     new Example(); 
    } 

    public Example() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setLayout(new GridBagLayout()); 
      setBorder(new EmptyBorder(20, 20, 20, 20)); 
      JTextField field = new JTextField(10); 
      LimitedRangeDocumentFilter filter = new LimitedRangeDocumentFilter(1, 1000); 
      filter.setLimitedRangeDocumentFilterListener(new LimitedRangeDocumentFilterListener() { 
       @Override 
       public void updateWouldBeInvalid(LimitedRangeDocumentFilter filter, String text) { 
        JOptionPane.showMessageDialog(TestPane.this, 
          text + " is not within " + filter.getMin() + "-" + filter.getMax() + " range", 
          "Error", 
          JOptionPane.ERROR_MESSAGE); 
       } 
      }); 
      ((AbstractDocument)field.getDocument()).setDocumentFilter(filter); 
      add(field); 
     } 

    } 

    public interface LimitedRangeDocumentFilterListener { 
     public void updateWouldBeInvalid(LimitedRangeDocumentFilter filter, String text); 
    } 

    public class LimitedRangeDocumentFilter extends DocumentFilter { 

     private int min; 
     private int max; 

     private LimitedRangeDocumentFilterListener listener; 

     public LimitedRangeDocumentFilter(int min, int max) { 
      this.min = min; 
      this.max = max; 
     } 

     public int getMin() { 
      return min; 
     } 

     public int getMax() { 
      return max; 
     } 

     public void setLimitedRangeDocumentFilterListener(LimitedRangeDocumentFilterListener listener) { 
      this.listener = listener; 
     } 

     @Override 
     public void insertString(DocumentFilter.FilterBypass fb, int offset, 
       String string, AttributeSet attr) 
       throws BadLocationException { 

      StringBuilder sb = new StringBuilder(string); 
      for (int i = sb.length() - 1; i >= 0; i--) { 
       char ch = sb.charAt(i); 
       if (!Character.isDigit(ch)) { 
        sb.deleteCharAt(i); 
       } 
      } 

      StringBuilder master = new StringBuilder(fb.getDocument().getText(0, fb.getDocument().getLength())); 
      master.insert(offset, sb.toString()); 
      if (wouldBeValid(master.toString())) { 
       super.insertString(fb, offset, sb.toString(), attr); 
      } else if (listener != null) { 
       listener.updateWouldBeInvalid(this, master.toString()); 
      } 
     } 

     @Override 
     public void replace(DocumentFilter.FilterBypass fb, 
       int offset, int length, String string, AttributeSet attr) throws BadLocationException { 
      if (length > 0) { 
       fb.remove(offset, length); 
      } 
      insertString(fb, offset, string, attr); 
     } 

     protected boolean wouldBeValid(String text) { 
      boolean wouldBeValid = false; 
      try { 
       int value = Integer.parseInt(text); 
       if (value >= min && value <= max) { 
        wouldBeValid = true; 
       } 
      } catch (NumberFormatException exp) { 
      } 
      return wouldBeValid; 
     } 
    } 

} 

См Implementing a Document Filter и DocumentFilter Examples для получения более подробной информации

 Смежные вопросы

  • Нет связанных вопросов^_^