- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的代码的目的是模仿 Google 文档的功能 - 当用户在一台机器上键入时,他们键入的字母会出现在另一台机器上。出于简单的目的,每台机器在图形用户界面中键入文本,主类处理所有更改。
每台机器都有一个“编辑器”,并链接到总共 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);
}
}
Editor 看起来像这样(两个弹出窗口,不是其余的):
制作编辑器的代码在这里:
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);
}
}
我的代码目前唯一的问题是文件内容主题,当我尝试更改通过编辑器传递的代码时。我收到很多“无法在通知内突变”和“空指针异常”错误。生成此代码的代码如下,是我已注释掉的部分。
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)到文件内容主题,让它更改文件内容主题,并通知所有编辑者?
让这一切发生的我的其他类(class)(不重要,但为清楚起见显示):
主题界面
/**
* 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 的帮助,代码答案位于所选答案的最后三个代码块上。
最佳答案
java.lang.IllegalStateException: Attempt to mutate in notification
被抛出是因为在 FileContentSubject
的这些行中:
@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();
}
FileContentSubject
的构造函数中的这一行:
textArea.getDocument().addDocumentListener(this);
表明您正在尝试从 DocumentListener
方法内部更改 textArea
的值。
正如指出的那样here , 您应该为此目的使用 DocumentFilter
。
这是 DocumentFilter
使用的一个简单工作示例(它将所有键入的字符替换为其大写版本):
//UpcaseFilter.java
//A simple DocumentFilter that maps lowercase letters to uppercase.
import javax.swing.*;
import javax.swing.text.*;
public class UpcaseFilter extends DocumentFilter {
public void insertString(DocumentFilter.FilterBypass fb, int offset,
String text, AttributeSet attr) throws BadLocationException {
fb.insertString(offset, text.toUpperCase(), attr);
}
// no need to override remove(): inherited version allows all removals
public void replace(DocumentFilter.FilterBypass fb, int offset, int length,
String text, AttributeSet attr) throws BadLocationException {
fb.replace(offset, length, text.toUpperCase(), attr);
}
public static void main(String[] args) {
DocumentFilter dfilter = new UpcaseFilter();
JTextArea jta = new JTextArea();
JTextField jtf = new JTextField();
((AbstractDocument) jta.getDocument()).setDocumentFilter(dfilter);
((AbstractDocument) jtf.getDocument()).setDocumentFilter(dfilter);
JFrame frame = new JFrame("UpcaseFilter");
frame.getContentPane().add(jta, java.awt.BorderLayout.CENTER);
frame.getContentPane().add(jtf, java.awt.BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 120);
frame.setVisible(true);
}
}
(以上例子取自Java Swing, 2nd Edition书,chapter 22。)
简而言之,问题在于您的代码中发生了这种情况:
Editor
实例(我们称它为 edt
)textArea
发生变化时...FileContentSubject
(因为它是一个 DocumentListener
)注意到该事件,然后通知它所有注册的观察者(包括 edt
! ) 调用他们的 update()
方法...edt
的 update()
方法改变了它的 textArea
并且...瞧!您正在尝试更改启动事件的 textArea
(在事件结束之前)!然后您所要做的就是找到一种不通知事件发起人的方法。下面的代码为此使用了 Document.putProperty()
和 Document.getProperty()
:它分离事件的源代码编辑器 (reference.detach(e);
), 将更改通知所有人,并重新附加它 (reference.attach(e);
)。
(此外,我用 String
替换了 FileContentSubject
的 JTextArea
,因为 String
就足够了.)
因此,这是更改后的 FileContentSubject
代码:
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
public class FileContentSubject implements Subject, DocumentListener {
// private JTextArea textArea; // removed as a String field will suffice
// private Document doc; // should not be a field!
private String state;
public String getState() {
return this.state;
}
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) {
Document doc = (Document) arg0.getDocument();
try {
// this.textArea.setText(doc.getText(0, doc.getLength()-1));
this.state = doc.getText(0, doc.getLength());
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Editor e = (Editor) doc.getProperty("ownerEditor");
reference.detach(e); // so it will not be notified of its own change
notifyAllObservers(); // tell everybody else to catch up with the changes
reference.attach(e); // reattaches the editor
}
@Override
public void removeUpdate(DocumentEvent arg0) {
Document doc = (Document) arg0.getDocument();
try {
// this.textArea.setText(doc.getText(0, doc.getLength()-1));
this.state = doc.getText(0, doc.getLength());
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Editor e = (Editor) doc.getProperty("ownerEditor");
reference.detach(e); // so it will not be notified of its own change
notifyAllObservers(); // tell everybody else to catch up with the changes
reference.attach(e); // reattaches the editor
}
// public String getJTextArea() {
// return textArea.getText();
// }
}
更改后的 Editor
的构造函数:
public Editor(FileContentSubject filecontentsubject) {
super("Editor");
initComponents();
this.reference = filecontentsubject;
textArea.getDocument().addDocumentListener(reference);
textArea.getDocument().putProperty("ownerEditor", this); // <---- ADDED LINE
}
和update()
:
@Override
public void update() {
//textArea.setText(reference.getJTextArea());
//textArea.setText(reference.temp);
textArea.setText(reference.getState()); // ADDED
}
就是这样!
关于Java - 关于一些代码的观察者模式。模仿同步文本更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16004086/
表架构 DROP TABLE bla; CREATE TABLE bla (id INTEGER, city INTEGER, year_ INTEGER, month_ INTEGER, val I
我需要拆分字符串/或从具有以下结构的字符串中获取更容易的子字符串。 字符串将来自 window.location.pathname 或 window.location.href,看起来像 text/n
每当将对象添加到数组中时,我都会尝试更新 TextView ,并在 TextView 中显示该文本,如下所示: "object 1" "object 2" 问题是,每次将新对象添加到数组时,它都会覆盖
我目前正在寻找使用 Java 读取网站可见文本并将其存储为纯文本字符串的方法。 换句话说,我想转换成这样: Hello stupid World进入“ Hello World ” 或者类似的东西 Un
我正在尝试以文本和 HTML 格式发送电子邮件,但无法正确发送正确的 header 。特别是,我想设置 Content-Type header ,但我找不到如何为 html 和文本部分单独设置它。 这
我尝试了上面的代码,但我无法绑定(bind)文本,我怎样才能将资源内部文本 bloc
我刚刚完成了 Space Shooter 教程,由于没有 GUIText 对象,所以我创建了 UI.Text 对象并进行了相应的编码。它在统一播放器中有效,但在构建 Web 应用程序后无效。我花了一段
我有这个代码: - (IBAction)setButtonPressed:(id)sender { NSUserDefaults *sharedDefaults = [[NSUserDefau
抱歉标题含糊不清,但我想不出我想在标题中做什么。无论如何,对于图像上的文本,我使用了 JLabel 文本并将其添加到图标中。 JLabel icon = new JLabel(new Imag
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我在将 Twitter 嵌入到我从 HTML 5 转换的 wordpress 运行网站时遇到问题。 我遇到的问题是推文不是我的自定义字体... 这是我无法使用任何 css 定位的 HTML 代码,我正
我正在尝试找到解决由于使用以下形式的代码而导致的冗余字符串连接问题的最佳方法: logger.debug("Entering loop, arg is: " + arg) // @1 在大多数情况下,
我写了这个测试 @Test public void removeRequestTextFromRouteError() throws Exception { String input = "F
我目前正在创建一个正则表达式来拆分所有匹配以下格式的字符串:&[文本],并且需要获取文本。字符串可能类似于:something &[text] &[text] everything &[text] 等
有没有办法将标题文本从一个词变形为另一个词,同时保留两个词中使用的字母?我看过的许多 css 文本动画大多是视觉的,很少有旋转整个单词的。 我想要做的是从一个词过渡,例如“BEACH”到“CHANGE
总结matplotlib绘图如何设置坐标轴刻度大小和刻度。 上代码: ?
我在容器 (1) 中创建了容器 (2)。你能帮忙如何向容器(1)添加文本吗?下面是我的代码 return Scaffold( body: Padding( padding: c
我似乎找不到任何人或任何人这样做过。我试图限制我们使用的图像数量,并想创建一个带有渐变作为其“颜色”的文本,并在其周围设置渐变轮廓/描边 到目前为止,我还没有看到任何将两者结合在一起的东西。 我可以自
我正在为视频游戏暗黑破坏神 2 使用 discord.py 构建一个不和谐机器人。其中一项功能要求机器人从暗黑破坏神 2 屏幕截图中提取项目的名称和属性。我目前正在为此使用 pytesseract,但
我很难弄清楚如何旋转 strip.text theme 中的属性来自 ggplot2 .我使用的是 R 版本 3.4.2 和 ggplot2 版本 2.2.1。 以下是 MWE 的数据。 > dput
我是一名优秀的程序员,十分优秀!