我的代码的目的是模仿 Google Docs 的功能——当用户在一台机器上键入时,他们键入的字母会出现在另一台机器上。为简单起见,每台机器在 gui 中键入文本,主类处理所有更改。
每台机器都有一个“编辑器”,并链接到总共 1 个“文件内容主题”。“文件内容主题”应该进行用户所做的更改并将更新的代码发送给所有“编辑器”
这从一个简单的驱动程序开始,我在其中创建一个文件内容主题,创建两个编辑器并将它们连接在一起
public class Driver {
public static void main(String[] args) {
FileContentSubject filecontentsubject = new FileContentSubject();
Editor e1 = new Editor(filecontentsubject);
Editor e2 = new Editor(filecontentsubject);
filecontentsubject.attach(e1);
filecontentsubject.attach(e2);
}
}
编辑器看起来像这样(两个弹出窗口,而不是其余窗口):
制作编辑器的代码在这里:
import javax.swing.*;
import java.util.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
public class Editor extends JFrame implements DocumentListener, Observer {
private FileContentSubject reference;
private Document doc;
private JScrollPane textAreaScrollPane;
private JTextArea textArea;
public Editor(FileContentSubject filecontentsubject) {
super("Editor");
initComponents();
this.reference = filecontentsubject;
textArea.getDocument().addDocumentListener(reference);
}
private void initComponents(){
textArea = new JTextArea();
textArea.setColumns(5);
textArea.setLineWrap(true);
textArea.setRows(50);
textArea.setWrapStyleWord(true);
textAreaScrollPane = new JScrollPane(textArea);
setLocation(600,100);
setSize(500,400);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(textArea, BorderLayout.CENTER);
}
@Override
public void changedUpdate(DocumentEvent arg0) {
}
@Override
public void insertUpdate(DocumentEvent arg0) {
reference.insertUpdate(arg0);
}
@Override
public void removeUpdate(DocumentEvent arg0) {
reference.removeUpdate(arg0);
}
@Override
public void update() {
//textArea.setText(reference.getJTextArea());
//textArea.setText(reference.temp);
}
}
我的代码现在唯一的问题是在File Content Subject中,当我尝试更改通过编辑器传递的代码时。我收到很多“不能在通知中变异”和一些“空指针异常”错误。生成此代码的代码如下,是我注释掉的部分。
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Position;
public class FileContentSubject implements Subject, DocumentListener {
private JTextArea textArea;
private Document doc;
private SubjectImpl reference;
@Override
public void attach(Observer o) {
reference.attach(o);
}
@Override
public void detach(Observer o) {
reference.detach(o);
}
@Override
public void notifyAllObservers() {
reference.notifyAllObservers();
}
public FileContentSubject(){
reference = new SubjectImpl();
textArea = new JTextArea();
textArea.setTabSize(5);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.getDocument().addDocumentListener(this);
}
@Override
public void changedUpdate(DocumentEvent arg0) {}
@Override
public void insertUpdate(DocumentEvent arg0) {
doc = (Document)arg0.getDocument();
// try {
// //this.textArea.setText(doc.getText(0, doc.getLength()-1));
// } catch (BadLocationException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
notifyAllObservers();
}
@Override
public void removeUpdate(DocumentEvent arg0) {
doc = (Document)arg0.getDocument();
// try {
// this.textArea.setText(doc.getText(0, doc.getLength()-1));
// } catch (BadLocationException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
notifyAllObservers();
}
public String getJTextArea(){
return textArea.getText();
}
}
所以我的问题是,如何将文本(通过编辑器传入 DocumentEvent)传递到文件内容主题中,让它更改文件内容主题,并通知所有编辑者?
我的其他课程使这一切发生(不重要,但为了清楚起见):
主题界面
/**
* Interface
*/
public interface Subject {
public void attach(Observer o);
public void detach(Observer o);
public void notifyAllObservers();
}
观察者界面
public interface Observer {
public void update();
}
SubjectImpl 类
import java.util.ArrayList;
import java.util.List;
public class SubjectImpl implements Subject {
private List <Observer> observers;
public SubjectImpl(){
observers = new ArrayList<Observer>();
}
@Override
public void attach(Observer o) {
observers.add(o);
}
@Override
public void detach(Observer o) {
observers.remove(o);
}
@Override
public void notifyAllObservers() {
for(Observer o: observers){
o.update();
}
}
}
回答
需要防止正在编辑自身的编辑器被更新。这是通过文档属性完成的,并将所有内容都保存在字符串中而不是 JTextArea 中。非常感谢 acdcjunior 的帮助,代码答案位于所选答案的最后三个代码块上。