你確實有三個問題......
- 更新時,首先是更新第二個文本組件,該組件是比較容易的。
- 當更新第二個文本組件時,更新第一個文本組件......好吧,REAL很快就會變得很複雜。
- 過濾輸入文本。這實際上是通過Implementing a Document Filter
相對容易的現在,真正的問題是#2,這是因爲你可以在一個骯髒的地方結束了真正的速度是第一場嘗試更新的第二場,這將觸發和事件這會導致第二個字段更新觸發的第一個字段以及導致第一個字段更新第二個字段的事件......並且您開始瞭解這個想法。
幸運的是,實際上鞦韆不會讓它壞,並會拋出一個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
需要它用於此偵聽更新
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) {
}
}
現在,這裏真正tripy部分是圍繞ignoreUpdates
國旗的「奴隸」 Document
。基本上,這是什麼做的是,當一個事件發生時,我們首先檢查哪個觸發事件的Document
的ignoreUpdates
標誌,如果是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
S,一個用於每個JTextArea
,我們接着創建兩個DocumentHandler
S,一個用於每個JTextArea
並提供相對Document
作爲從(rightDoc
爲left
和leftDoc
爲right
),這允許事件跨越並更新到發生
這使我們能夠建立類似...
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) {
}
}
}
好了,所以這是大約一半的什麼我們需要,接下來我們需要能夠過濾被輸入到其中一個字段的內容,以便我們可以改變,這可以通過Implementing a Document Filter