| Цитата(w1nd @ 14.12.2006, 23:26) | | А вы не приводите тонны кода, сделайте небольшой пример. Я делал свой DocumentFilter в своем форматёре для JFormattedTextField - все отлично работает. |
OK. Попробую, ну вроде как мысль иллюстрирует.
Итак, сперва простейший фильтр.
| Код | package ttt;
import java.awt.Toolkit; import javax.swing.text.AbstractDocument; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DocumentFilter;
/** * пытается запретить пользователю вводить двойку в строку и все. */ public class TestFilter extends DocumentFilter { private AbstractDocument _doc; public TestFilter (AbstractDocument docArg) { _doc= docArg; //Запомним ссылку на документ } public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { fb.remove(offset, length); //Здесь ничего не трогаем- удаляйте на здоровье } public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { String newStr= _doc.getText(0, _doc.getLength()); newStr= newStr.substring(0,offset) + string+ newStr.substring(offset+1, _doc.getLength()); /* Проверим строку на корректность, в примере мы запретим вводить туда, ну скажем * цифру 2, (помним, это ПРИМЕР - на практике там не простая проверка) */ if(isStringCorrect(newStr)) { fb.insertString(offset, string, attr); } else { beep(); }//if } public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException { String newStr= _doc.getText(0, _doc.getLength()); newStr= newStr.substring(0,offset) + string+ newStr.substring(offset+length, _doc.getLength()); if(isStringCorrect(newStr)) { fb.replace(offset, length, string, attr); } else { beep(); }//if } /** * @param stringArg - строка для проверки * @return - true, если строка удовлетворяет нашему условию, т.е. не содержит '2' */ protected boolean isStringCorrect(String strToTestArg) { return !strToTestArg.contains("2"); } private final void beep() { Toolkit.getDefaultToolkit().beep(); } }
|
Теперь не менее простой форматтер, скорее всего, уже здесь я допускаю какую-то глупую ошибку. Вроде как я так понял у SUN, что назначение фильтра для JFormattedTextField идет через переопределение getDocumentFilter(), но это не работает. 
| Код | ackage ttt;
import java.text.DecimalFormat; import javax.swing.text.AbstractDocument; import javax.swing.text.DocumentFilter;
/** * Все, что нам надо от этого класса, так это попытаться хоть как-то * впихнуть фильтр для ДИНАМИЧЕСКОЙ проверки вводимого значения, т.е. * пользователь вводит двойку, а она не вводится и раздается гудок динамика. */ public class TestDecimalFormatter extends DecimalFormat { private static final long serialVersionUID= 1L; private TestFilter _testFilter; public TestDecimalFormatter(AbstractDocument docArg) { super(); _testFilter= new TestFilter(docArg); //Задаем поведение отличное от стандартного, чтобы убедиться, что сам форматер //вообще используется - и убеждаемся, что таки да, т.е. цифры начинают группироваться по 4, а //не по 3, как это задано по-умолчанию this.setGroupingSize(4); } /** * Собственно на это метод у меня и была вся надежда. :( */ protected DocumentFilter getDocumentFilter() { return _testFilter; }
}
|
Собственно поле, отличающееся от стандартного только попыткой задать свой форматтер, сама попытка срабатывает, т.е. можно в форматторе, скажем задать другой разделитель групп и это будет учтено, а вот фильтр вообще не работает!
| Код | package ttt;
import java.text.Format; import javax.swing.JFormattedTextField; import javax.swing.text.AbstractDocument; import javax.swing.text.DefaultFormatterFactory; import javax.swing.text.NumberFormatter;
//Для этого-то поля и впихнем свой фильтр public class TestJFormattedTextField extends JFormattedTextField { private static final long serialVersionUID= 1L; //Конструкторы ничем не отличаются от таковых в JFormattedTextField public TestJFormattedTextField () { super(); init(); } public TestJFormattedTextField (Object value) { super(value); init(); } public TestJFormattedTextField(AbstractFormatterFactory factory, Object currentValue) { super(factory, currentValue); init(); } public TestJFormattedTextField (Format format) { super(format); init(); }
private void init() { TestDecimalFormatter df= new TestDecimalFormatter((AbstractDocument) this.getDocument()); setFormatterFactory(new DefaultFormatterFactory(new NumberFormatter(df))); } }
|
Класс для тестирования всего получившегося:
| Код | package ttt;
import java.awt.Container; import java.awt.FlowLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.text.AbstractDocument;
public class TestGUI extends JFrame { private static final long serialVersionUID= 1L; public static void main(String[] arg) { TestGUI testGUI= new TestGUI(); Container pane= testGUI.getContentPane(); pane.setLayout(new FlowLayout()); //Первым добавим обычное JTextField чтобы проверить, что наш фильтр //вообще работает - и он таки работает отлично. JTextField fieldGood= new JTextField("114343434",9); AbstractDocument doc1 = (AbstractDocument)fieldGood.getDocument(); doc1.setDocumentFilter(new TestFilter(doc1)); pane.add(new JLabel("It works fine")); pane.add(fieldGood); //Теперь добавим наше JFormattedTextField и убедимся, что фильтр не работает TestJFormattedTextField fieldBad= new TestJFormattedTextField(); fieldBad.setColumns(25); pane.add(new JLabel("It does not look at any my filter!")); pane.add(fieldBad); testGUI.setDefaultCloseOperation(EXIT_ON_CLOSE); testGUI.setVisible(true); testGUI.pack(); } }
|
|