Использование DocumentFilter.FilterBypass

Я хочу иметь такой метод на моем DocumentFilter

public void replaceUpdate(int offset, int length, String text) {
        try {
            super.replace(byPass, offset, length, text, null);
        } catch (BadLocationException ex) {
            //error
        }
}

В настоящее время, чтобы получить экземпляр FilterBypass (метод byPass выше), мне нужно получить из переопределенного метода insertString :

private FilterBypass byPass;

@Override
    public void insertString(DocumentFilter.FilterBypass fb,
            int offset, String string, AttributeSet att)
            throws BadLocationException {
        byPass = fb;
        //some stuff here
        super.insertString(fb, offset, string, att);
    }

Но это вызывает у меня некоторые проблемы. Может ли кто-нибудь предложить другой способ получить FilterBypass? Я не могу найти способ получить ссылку на FilterBypass по-другому.

Если бы я должен был переопределить его методы, как это должно быть?


person Giannis    schedule 19.02.2012    source источник
comment
Я настоятельно рекомендую вам создать и опубликовать sscce (пожалуйста, взгляните на ссылку!), которая показывает вашу проблему. Этот код небольшой, компилируется для нас, запускается для нас, не имеет постороннего кода, не связанного с вашей проблемой, и демонстрирует проблему для всех.   -  person Hovercraft Full Of Eels    schedule 19.02.2012
comment
Я считаю, что ясно заявляю, что мне нужен другой способ получить FilterBypass, поскольку этот способ вызывает проблемы.   -  person Giannis    schedule 19.02.2012
comment
Единственный известный мне способ получить соответствующий объект FilterBypass — это тот, который предоставляется JVM при вызове переопределения метода DocumentFilter. Подобно объекту Graphics и методу paint/paintComponent, я считаю, что этот объект не сохраняется между вызовами метода. Думаю, я запутался в вашей цели. Кажется, вы хотите вызывать методы фильтра без управления событиями. Когда будет вызываться ваш replaceUpdate? Будет ли это происходить из одного из переопределенных методов DocumentFilter?   -  person Hovercraft Full Of Eels    schedule 19.02.2012
comment
Переопределенные методы вызываются, когда пользователь печатает и фильтрует ввод. replaceUpdate вызывается из внешнего источника. Я не хочу, чтобы внешний источник был отфильтрован, и я просто хочу, чтобы он попал в документ. Вот почему у меня есть replaceUpdate.   -  person Giannis    schedule 19.02.2012
comment
Что если текст добавляется внешним источником, а затем пользователь добавляет текст? Как отличить, что вводит пользователь, а что вводит внешний источник? У меня есть ощущение, что ваше решение состоит не в том, чтобы получить FilterBypass каким-то необычным способом, а в изменении логики ваших методов DocumentFilter, но я не могу рекомендовать больше, не зная больше. Опять же, я считаю, что sscce очень поможет.   -  person Hovercraft Full Of Eels    schedule 19.02.2012


Ответы (2)


Например, вот SSCCE с DocumentFilter, который не позволяет пользователю вводить числа в документ, но позволяет делать это Swing Timer.

import java.awt.event.*;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.text.*;

public class DocFilterPanel extends JPanel {
   private JTextArea textArea = new JTextArea(12, 50);
   private MyDocFilter myDocFilter = new MyDocFilter();

   public DocFilterPanel() {
      ((PlainDocument) textArea.getDocument()).setDocumentFilter(myDocFilter);
      int vsbPolicy = JScrollPane.VERTICAL_SCROLLBAR_ALWAYS;
      int hsbPolicy = JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
      add(new JScrollPane(textArea, vsbPolicy , hsbPolicy));

      int timerDelay = 1000;
      new Timer(timerDelay , new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            myDocFilter.setFilter(false);
            textArea.append("12345\n");
            myDocFilter.setFilter(true);
         }
      }).start();
   }

   private static void createAndShowGui() {
      DocFilterPanel docFilterPanel = new DocFilterPanel();

      JFrame frame = new JFrame("DocFilterTest");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(docFilterPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class MyDocFilter extends DocumentFilter {
   private static final String REMOVE_REGEX = "\\d";
   private boolean filter = true;

   public boolean isFilter() {
      return filter;
   }

   public void setFilter(boolean filter) {
      this.filter = filter;
   }

   @Override
   public void insertString(FilterBypass fb, int offset, String text,
         AttributeSet attr) throws BadLocationException {
      if (filter) {
         text = text.replaceAll(REMOVE_REGEX, "");
      }
      super.insertString(fb, offset, text, attr);

   }

   @Override
   public void replace(FilterBypass fb, int offset, int length, String text,
         AttributeSet attrs) throws BadLocationException {
      if (filter) {
         text = text.replaceAll(REMOVE_REGEX, "");
      }
      super.replace(fb, offset, length, text, attrs);

   }
}
person Hovercraft Full Of Eels    schedule 19.02.2012
comment
Я полагал, что при использовании этого флага возникнут проблемы с параллелизмом, но, попробовав, оказалось, что их нет. Это также выглядит лучше, чем мое решение. ты - person Giannis; 19.02.2012
comment
@latusaki: я тоже беспокоился об этом. Я полагаю, вы всегда можете отключить JTextField при добавлении текста из программы, а затем снова включить его. - person Hovercraft Full Of Eels; 19.02.2012
comment
Я не уверен, имеет ли это какое-то значение, но я использую SwingUtilities.invokeLater для вызова DocumentFilter. В любом случае у меня до сих пор не было проблем, надеюсь, у меня не будет в будущем эфире. - person Giannis; 20.02.2012

Мне понравилось решение @hovercraft, но оно вызвало проблемы с параллелизмом. Я решил это, синхронизировав переключение фильтра в текстовой области. Как это:

synchronized (textArea) {
    myDocFilter.setFilter(false);
    textArea.append("12345\n");
    myDocFilter.setFilter(true);
}
person Benjamin Hammer Nørgaard    schedule 06.03.2014