簡體   English   中英

Java觀察者/可觀察的更新

[英]Java Observer/Observable update

我嘗試應用Observable / Observer模式,但是當我嘗試更改JTextPane的textfield時,我的代碼出了點問題。

我有3個類, PlayControllerSecondWindow這是它們的代碼示例。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM