2016-12-20 8 views
2

Observable/Observerパターンを適用しようとしましたが、JTextPaneのテキストフィールドを変更しようとすると、コードに問題があります。Java Observer/Observable update

私は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 
    } 

私は(txt.setText(c.getText)命令のような)テキストフィールドに変数cを入れて管理することはできません。私はそれがメソッドの更新を読んでいると確信していますが、私はそれが動作することを確認する方法を知らない。

答えて

4

ヒント:Observerable API当たりnotifyObserversメソッドは、パラメータとして任意のオブジェクトを受け入れるオーバーロードを有する:

public void notifyObservers(Object arg) 

これは偶数列とすることができます。そして、Observer APIに従って、このオブジェクトはオブザーバのupdateメソッドに渡され、そこで使用することができます。

void update(Observable o, 
     Object arg) 

のarg - notifyObserversメソッドに渡される引数。ここ


セパレート側の問題:

contentPane.setLayout(NULL);

ほとんどのスイング愛好家にとって、これは七面鳥の爪のようなものです。痛いです。ヌルレイアウトとsetBounds()は、複雑なGUIを作成する最も簡単で最良の方法のようにSwingの初心者のように思えるかもしれませんが、Swing GUIを使用すると、より多くの深刻な問題が発生します。 GUIのサイズが変更されたときにコンポーネントのサイズを変更することはありません。これらのコンポーネントは、拡張または維持するロイヤルウィジェットであり、スクロールペインに配置すると完全に失敗し、元のプラットフォームとは異なるすべてのプラットフォームまたは画面解像度で表示されます。その代わりに、レイアウトマネージャを学習して習得し、それぞれ独自のレイアウトマネージャを使用してJPanelsをネストして、すべてのOSでよく見える魅力的で複雑なGUIを作成したいと思うでしょう。


サイド発行番号2:あなたのコードのSwing GUIは非常によくSwingのイベントディスパッチスレッドまたはEDTのオフに観察で通知することができているので、スレッドセーフでスイングされていません。この単純なプログラムでは頻繁にまたは重大な問題を引き起こす可能性は低いですが、一般に、可能ならばObserver/ObservableではなくSwingPropertyChangeSupportとPropertyChangeListenersを使用する方がよいでしょう。


サイドの問題
この:

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()); 
     } 
    } 
}