【发布时间】:2015-01-31 11:12:45
【问题描述】:
我正在使用观察者模式编写一个简单的 java Canvas 应用程序,因此我可以创建多个同步窗口(视图)。但是我遇到了一个问题,多个视图在调试时同步,但在实际运行时不同步。
谁能帮我解决这个问题?
我是这样实现的(我接受了@Hovercraft Full Of Eels 的建议,并尝试创建和发布一个最小、完整且可验证的示例程序。):
监听器,它是一个接口:
public interface CanvasListener {
void dragMouse(MouseEvent e);
}
我有一个模型,用来不断通知所有听众;
public class CanvasModel{
private List<CanvasListener> listeners;
//...other functions
public void mouseDragged(MouseEvent e) {
for(CanvasListener listener: listeners){
listener.dragMouse(e);
}
}
}
一个视图实现了Listener,我重写了dragMouse函数并实现了画布:
public class CanvasView implements CanvasListener {
private CanvasModel model;
private JPanel panel;
public CanvasView(CanvasModel myModel) {
// some initializations
panel.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
model.mouseDragged(e);
}
});
}
@Override
public void dragMouse(MouseEvent e) {
Graphics g = panel.getGraphics();
g.drawLine(a, b, c, d); //parameters here are not real
g.dispose();
}
}
在主课中,我创建了 2 个视图。
public static void main(String[] args){
CanvasModel model = new CanvasModel();
new CanvasView(model);
new CanvasView(model);
}
但是如果我在一个窗口上绘制,只有一个显示图形,如picture所示
但是如果我追溯代码,两个窗口都会反映图形,如picture所示
谢谢!
【问题讨论】:
-
要获得更好的帮助,请考虑创建并发布Minimal, Complete, and Verifiable Example Program。我们不想看到你的整个程序,而是你应该将你的代码压缩成仍然可以编译的最小部分,没有与你的问题无关的额外代码,但仍然可以证明你的问题。并且模型不应调用 dragMouse 或其他侦听器方法。它应该只是更改其状态,然后通过调用通知方法通知侦听器状态已更改,就是这样。
-
另外,您的视图不应使用通过在组件上调用
getGraphics()获得的 Graphics 对象进行绘制,但这是另一个讨论的主题。 -
@HovercraftFullOfEels 感谢您的建议!
-
不客气。理解模型应该完全不知道视图和控件,这意味着它不应该知道任何关于它们的字段或它们的方法,并且不应该调用任何内容。它所知道的是,当它的状态发生变化时,它必须将变化通知侦听器,仅此而已。这是绝对必要的,因为模型应该可供各种控件和视图使用。
-
您明白,除非您改进,否则您提出的问题仍然无法回答。我再次建议您创建并发布mcve(请查看链接)。
标签: java swing model-view-controller observer-pattern synchronize