[英]Java Observer/Observable update
我尝试应用Observable / Observer模式,但是当我尝试更改JTextPane
的textfield时,我的代码出了点问题。
我有3个类, Play
, Controller
和SecondWindow
这是它们的代码示例。
public class Play() {
Controller c = new Controller();
SecondWindow sw = new SecondWindow();
c.addObserver(sw)
c.setText("blabla");
}
我的类Controller
:
public class Controller extends Observable(){
private String text ="";
private static Controller getInstance() {
if (instance == null) {
instance = new Controller();
}
return instance;
}
public void setText(String s) {
text = s;
setChanged();
notifyObservers();
}
}
和SecondWindow
:
public class SecondWindow extends JFrame implements Observer{
private JPanel contentPane;
private Controller c;
private JTextPane txt = new JTextPane();
public SecondWindow () {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SecondWindow frame = new SecondWindow();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public SecondWindow() {
initComponents();
createEvents();
c = Controller.getInstance();
}
public void initComponents() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(1000, 0, 300,500);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
txt.setBounds(0, 0, 280, 460);
txt.enable(false);
contentPane.add(txt);
}
public void update(Observable arg0 , Object arg1){
// Things to change here
}
我无法将变量c
放在textField中(例如txt.setText(c.getText)
指令)。 我确定它读取方法更新,但是我不知道如何确保它有效。
提示:根据Observerable API ,notifyObservers方法具有一个重载,该重载接受任何对象作为参数:
public void notifyObservers(Object arg)
甚至可以是一个字符串。 然后按照Observer API的要求 ,将此对象传递到观察器中的update方法中,您可以在其中使用它。
void update(Observable o, Object arg)
arg-传递给notifyObservers方法的参数。
单独问题在这里:
contentPane.setLayout(NULL);
对于大多数Swing爱好者来说,看到这就像在黑板上钉钉子一样-十分痛苦。 尽管null布局和setBounds()
似乎是Swing新手喜欢创建复杂GUI的最简单和最佳方法,但您创建的Swing GUI越多,使用它们时将遇到的困难就越大。 当GUI调整大小时,它们不会重新调整组件的大小;它们是需要增强或维护的皇家女巫;放置在滚动窗格中时,它们会完全失败;在所有平台或与原始分辨率不同的屏幕分辨率下查看时,它们看起来都是令人毛骨悚然的。 相反,您将需要学习和学习布局管理器,然后嵌套JPanels,每个JPanels都使用其自己的布局管理器来创建令人愉悦且复杂的GUI,在所有OS上都看起来不错。
侧问题二:你的代码是不是Swing线程安全的,因为Swing GUI的很可能是由观测到过 Swing事件分派线程或EDT的通知。 尽管使用此简单程序不太可能导致频繁或严重的问题,但是通常最好使用SwingPropertyChangeSupport和PropertyChangeListeners,而不是Observer / Observable。
下一期
这个:
public class Controller extends Observable(){
是不可编译的/犹太Java。 对于SecondWindow类的重复的无参数构造函数,该方法相同。 是的,我们知道您要执行的操作,但是要理解其他人的代码已经很困难了,您真的不想通过发布某种无法编译的代码来使其变得更困难,请相信我。
例如,可以使用PropertyChangeListeners在Swing中实现一些简单的操作,如下所示:
import java.util.concurrent.TimeUnit;
public class Play2 {
public static void main(String[] args) {
Model2 model2 = new Model2();
View2 view2 = new View2();
new Controller2(model2, view2);
view2.show();
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// one of the few times it's OK to ignore an exception
}
String text = String.format("Counter Value: %d", i);
model2.setText(text);
}
}
}
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
public class Model2 {
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
public static final String TEXT = "text"; // name of our "bound" property
private String text = "";
public String getText() {
return text;
}
public void setText(String text) {
String oldValue = this.text;
String newValue = text;
this.text = text;
pcSupport.firePropertyChange(TEXT, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(name, listener);
}
}
import javax.swing.*;
public class View2 {
private JPanel mainPanel = new JPanel();
private JTextField textField = new JTextField(10);
public View2() {
textField.setFocusable(false);
mainPanel.add(new JLabel("Text:"));
mainPanel.add(textField);
}
public JPanel getMainPanel() {
return mainPanel;
}
public void setText(String text) {
textField.setText(text);
}
public void show() {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("View");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(getMainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class Controller2 {
private Model2 model2;
private View2 view2;
public Controller2(Model2 model2, View2 view2) {
this.model2 = model2;
this.view2 = view2;
model2.addPropertyChangeListener(Model2.TEXT, new ModelListener());
}
private class ModelListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
view2.setText((String) pcEvt.getNewValue());
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.