У тебя на самом деле три проблемы...
- Обновление второго текстового компонента при обновлении первого, что относительно просто.
- Обновляйте первый текстовый компонент, когда обновляется второй... ну, это ОЧЕНЬ сложно, ОЧЕНЬ быстро.
- Отфильтруйте текст по мере его ввода. На самом деле это относительно легко сделать с помощью реализации фильтра документов.
Теперь реальная проблема № 2, потому что вы можете очень быстро оказаться в неприятном месте, поскольку первое поле пытается обновить второе поле, которое срабатывает, и событие, которое заставляет второе поле обновлять первое поле, которое срабатывает и событие, которое заставляет первое поле обновлять второе поле... и вы начинаете понимать эту идею.
К счастью, Swing на самом деле не допустит, чтобы все стало так плохо, и выдаст IllegalStateException
Чтобы преодолеть это, вам нужен какой-то способ узнать, когда обновление Document
инициируется подчиненным полем или когда оно инициируется чем-то еще (например, setText
вызывается, когда пользователь печатает или вставляет текст в поле поле) и игнорировать некоторые из этих событий
Теперь, наверное, есть действительно крутой и простой способ сделать это, но мой мозг сегодня не в «простом» режиме, извините.
Итак, я начинаю с пользовательского Document
, у него есть флаг, который позволяет мне проверять его состояние.
public class MirrorDocument extends PlainDocument {
private boolean ignoreUpdates;
public void setIgnoreUpdates(boolean ignoreUpdates) {
this.ignoreUpdates = ignoreUpdates;
}
public boolean isIgnoreUpdates() {
return ignoreUpdates;
}
}
Теперь я определяю DocumentListener
для отслеживания изменений в Document
. Этот DocumentListener
берет "ведомый" Document
, который используется этим слушателем для обновления
public static class DocumentHandler implements DocumentListener {
private MirrorDocument slaveDocument;
private boolean ignoreUpdates = false;
public DocumentHandler(MirrorDocument slaveDocument) {
this.slaveDocument = slaveDocument;
}
@Override
public void insertUpdate(DocumentEvent e) {
Document doc = e.getDocument();
if (doc instanceof MirrorDocument) {
MirrorDocument md = (MirrorDocument) doc;
if (!md.isIgnoreUpdates()) {
try {
String text = e.getDocument().getText(e.getOffset(), e.getLength());
slaveDocument.setIgnoreUpdates(true);
slaveDocument.insertString(e.getOffset(), text, null);
} catch (BadLocationException ex) {
ex.printStackTrace();
} finally {
slaveDocument.setIgnoreUpdates(false);
}
}
}
}
@Override
public void removeUpdate(DocumentEvent e) {
Document doc = e.getDocument();
if (doc instanceof MirrorDocument) {
MirrorDocument md = (MirrorDocument) doc;
if (!md.isIgnoreUpdates()) {
try {
slaveDocument.setIgnoreUpdates(true);
slaveDocument.remove(e.getOffset(), e.getLength());
} catch (BadLocationException ex) {
ex.printStackTrace();
} finally {
slaveDocument.setIgnoreUpdates(false);
}
}
}
}
@Override
public void changedUpdate(DocumentEvent e) {
}
}
Самое интересное здесь связано с флагом ignoreUpdates
. По сути, когда происходит событие, сначала мы проверяем флаг ignoreUpdates
элемента Document
, вызвавшего событие, и, если это false
, мы устанавливаем флаг ignoreUpdates
элемента slaveDocument
в значение true
, что предотвращает обработку DocumentListener
любого нового события. события, а затем обновить slaveDocument
Хорошо, это может показаться немного странным, и мне очень жаль, но поверьте мне, это будет иметь смысл... (однажды... и когда это произойдет, вы сможете объяснить мне это в ответ)
Итак, далее нам нужно все создать и склеить целиком...
JTextArea left = new JTextArea(10, 20);
JTextArea right = new JTextArea(10, 20);
MirrorDocument leftDoc = new MirrorDocument();
MirrorDocument rightDoc = new MirrorDocument();
left.setDocument(leftDoc);
right.setDocument(rightDoc);
leftDoc.addDocumentListener(new DocumentHandler(rightDoc));
rightDoc.addDocumentListener(new DocumentHandler(leftDoc));
Итак, мы создаем два JTextArea
s, left
и right
. Мы создаем два MirrorDocument
, по одному для каждого JTextArea
, затем мы создаем два DocumentHandler
, по одному для каждого JTextArea
, и предоставляем противоположный Document
в качестве ведомого (rightDoc
для left
и leftDoc
для right
), это позволяет происходить пересечению событий и обновлению.
Это позволяет нам настроить что-то вроде...
![Зеркальные текстовые области](https://i.stack.imgur.com/mKmZ0.gif)
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
public class MirrorTextAreas {
public static void main(String[] args) {
new MirrorTextAreas();
}
public MirrorTextAreas() {
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() {
JTextArea left = new JTextArea(10, 20);
JTextArea right = new JTextArea(10, 20);
setLayout(new GridLayout(1, 2));
add(new JScrollPane(left));
add(new JScrollPane(right));
MirrorDocument leftDoc = new MirrorDocument();
MirrorDocument rightDoc = new MirrorDocument();
left.setDocument(leftDoc);
right.setDocument(rightDoc);
leftDoc.addDocumentListener(new DocumentHandler(rightDoc));
rightDoc.addDocumentListener(new DocumentHandler(leftDoc));
}
}
public class MirrorDocument extends PlainDocument {
private boolean ignoreUpdates;
public void setIgnoreUpdates(boolean ignoreUpdates) {
this.ignoreUpdates = ignoreUpdates;
}
public boolean isIgnoreUpdates() {
return ignoreUpdates;
}
}
public static class DocumentHandler implements DocumentListener {
private MirrorDocument slaveDocument;
private boolean ignoreUpdates = false;
public DocumentHandler(MirrorDocument slaveDocument) {
this.slaveDocument = slaveDocument;
}
@Override
public void insertUpdate(DocumentEvent e) {
Document doc = e.getDocument();
if (doc instanceof MirrorDocument) {
MirrorDocument md = (MirrorDocument) doc;
if (!md.isIgnoreUpdates()) {
try {
String text = e.getDocument().getText(e.getOffset(), e.getLength());
slaveDocument.setIgnoreUpdates(true);
slaveDocument.insertString(e.getOffset(), text, null);
} catch (BadLocationException ex) {
ex.printStackTrace();
} finally {
slaveDocument.setIgnoreUpdates(false);
}
}
}
}
@Override
public void removeUpdate(DocumentEvent e) {
Document doc = e.getDocument();
if (doc instanceof MirrorDocument) {
MirrorDocument md = (MirrorDocument) doc;
if (!md.isIgnoreUpdates()) {
try {
slaveDocument.setIgnoreUpdates(true);
slaveDocument.remove(e.getOffset(), e.getLength());
} catch (BadLocationException ex) {
ex.printStackTrace();
} finally {
slaveDocument.setIgnoreUpdates(false);
}
}
}
}
@Override
public void changedUpdate(DocumentEvent e) {
}
}
}
Итак, это примерно половина того, что нам нужно, затем нам нужно иметь возможность фильтровать содержимое, введенное в одно из полей, чтобы мы могли его изменить, это можно сделать с помощью Реализация фильтра документов
person
MadProgrammer
schedule
08.10.2015