【问题标题】:Java Observer/Observable pattern does not NotifyJava Observer/Observable 模式不通知
【发布时间】:2011-09-26 02:57:01
【问题描述】:

我正在尝试使用 MVC 模式使用 SWT 构建一个简单的 Java 应用程序。我希望能够在后台发生某些事情时自动更新视图,因此我尝试使用 Observer/Observable 模式,但是当我的 Observable 更改时,我的 Observer 似乎永远不会收到通知。

代码如下:

Launcher.java(主类)

public class Launcher {

    public static void main(String[] args) {
        Application app = new Application();
        PenguinView v = new PenguinView(app);
        Controller api = new Controller(app, v);
    }

}

Application.java(后台应用程序)

public class Application {
    private Penguin _myPenguin;

    public Application() {
        _myPenguin = new Penguin();
        new Thread(_myPenguin).start();
    }

    public Penguin getPenguin() {
        return _myPenguin;
    }
}

Penguin.java(模型,我的 Observable)

public class Penguin extends Observable implements Runnable {
    private String _color;
    private boolean _isHappy;
    private int _myRocks;

    public Penguin() {
        _color = "Black";
        _isHappy = true;
        _myRocks = 0;
    }

    public void paint(String color) {
        _color = color;
        System.out.println("My new color is " + _color);
        setChanged();
        notifyObservers();
    }

    public String getColor() {
        return _color;
    }

    public void upset() {
        _isHappy = false;
        setChanged();
        notifyObservers();
    }

    public void cheerUp() {
        _isHappy = true;
        setChanged();
        notifyObservers();
    }

    public boolean isHappy() {
        return _isHappy;
    }

    public void run() {
        // Penguin starts walking and find rocks!
        while(true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            iFoundRock();
        }
    }

    private void iFoundRock() {
        _myRocks++;
        System.out.println("I now have " + _myRocks + " rocks");
        setChanged();
        notifyObservers();
    }

}

PenguinView.java(SWT 视图,我的观察者)

public class PenguinView implements Observer {
    private Application _app;

    private Display _d;
    private Shell _s;

    private Label _penguinColor;
    private Label _penguinHumor;
    private Label _penguinRocks;
    private Button _upset;
    private Button _cheerUp;
    private Text _newColor;
    private Button _paint;


    public PenguinView(Application app) {
        _app = app;
        _d = new Display();
        _s = new Shell();

        RowLayout rl = new RowLayout();
        rl.marginWidth = 12;
        rl.marginHeight = 12;
        _s.setLayout(rl);

        new Label(_s, SWT.BORDER).setText("Penguin Color: ");
        _penguinColor = new Label(_s, SWT.BORDER);
        _penguinColor.setText(_app.getPenguin().getColor());

        new Label(_s, SWT.BORDER).setText(" Humor: ");
        _penguinHumor = new Label(_s, SWT.BORDER);
        String humor = _app.getPenguin().isHappy() ? "Happy" : "Sad";
        _penguinHumor.setText(humor);

        new Label(_s, SWT.BORDER).setText(" Rocks: ");
        _penguinRocks = new Label(_s, SWT.BORDER);
        _penguinRocks.setText(String.valueOf(_app.getPenguin().howManyRocks()));

        _upset = new Button(_s, SWT.PUSH);
        _upset.setText(":(");
        _upset.addListener(SWT.Selection, new Listener(){
            public void handleEvent(Event e) {
                _penguinHumor.setText("Sad");
            }
        });

        _cheerUp = new Button(_s, SWT.PUSH);
        _cheerUp.setText(":)");
        _cheerUp.addListener(SWT.Selection, new Listener(){
            public void handleEvent(Event e) {
                _penguinHumor.setText("Happy");
            }
        });

        _newColor = new Text(_s, SWT.BORDER);

        _paint = new Button(_s, SWT.PUSH);
        _paint.setText("Paint!");
        _paint.addListener(SWT.Selection, new Listener(){
            public void handleEvent(Event e) {
                //_penguinColor.setText(_newColor.getText());
                _app.getPenguin().paint(_newColor.getText());
            }
        });

        _s.pack();
        _s.open();
        while (!_d.isDisposed()) {
            if (!_d.readAndDispatch()) {
                _d.sleep();
            }
        }
    }

    public void update(Observable obs, Object obj) {
        System.out.println("I go here!");
        _penguinRocks.setText(String.valueOf(((Penguin)obs).howManyRocks()));
        if(obs.equals(_app.getPenguin())) {
            _penguinRocks.setText(String.valueOf(((Penguin)obs).howManyRocks()));
        }
    }

    public void update(Observable obs) {
        System.out.println("I go there!");
    }

Controller.java(控制器)

public class Controller {
    Application _app;
    PenguinView _v;

    public Controller(Application app, PenguinView v) {
        _app = app;
        _v = v;

        // Set observer
        _app.getPenguin().addObserver(_v);
    }

}

输出

I now have 1 rocks
I now have 2 rocks
My new color is Blue
I now have 3 rocks
I now have 4 rocks

你知道我做错了什么吗?

谢谢!

【问题讨论】:

  • 您的视图在什么时候注册为 Penguin 实例的观察者?我似乎找不到那个 LOC(也许我在某个地方错过了它......)
  • 你的方法 notifyObservers() 在哪里?
  • @Brian Driscoll:在控制器的构造函数中:_app.getPenguin().addObserver(_v);
  • @talnicolas:在Penguin 类的iFoundRock() 方法中
  • @talnicolas 我猜它是在基类中实现的。在 SWT 中不确定它是否需要被覆盖。

标签: java model-view-controller swt observer-pattern


【解决方案1】:

据我所知,PenguinView 构造函数中的 while 循环阻塞了您的主线程,因此 Controller 永远不会被实例化并且永远不会添加观察者。

【讨论】:

  • 是的,我想通了。但是我对 SWT 有另一个问题:一旦我实例化了我的视图,主线程就卡在循环中,我无法实例化我的控制器(我不能在视图之前实例化它,因为它需要对视图的引用实例)
  • 您好,我也有类似的问题。请问你有解决办法吗?
  • 不要在你的构造函数中放置无限循环,将它们放入你从 main() 调用的另一个方法中。如果这不起作用,请将您的代码放在一个新问题中。
猜你喜欢
  • 2017-11-13
  • 1970-01-01
  • 2017-11-13
  • 1970-01-01
  • 1970-01-01
  • 2016-07-23
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
相关资源
最近更新 更多