2016-12-20 4 views
2

Я попытался применить шаблон Observable/Observer, но при попытке изменить текстовое поле JTextPane я попытался применить шаблон Observable/Observer.Обновление Java Observer/Observable

У меня есть 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) инструкции). Я уверен, что он читает обновление метода, но я не знаю, как убедиться, что он работает.

ответ

4

Подсказка: согласно Observerable API метод notifyObservers имеет перегрузку, которая принимает любой объект в качестве параметра:

public void notifyObservers(Object arg) 

Это может быть даже строка. И согласно Observer API, этот объект затем передается методу обновления в наблюдателе, и вы можете использовать его там.

void update(Observable o, 
     Object arg) 

Arg - аргумент передается методу notifyObservers.


Отдельные второстепенный вопрос здесь:

contentPane.setLayout (нуль);

Для большинства поклонников Swing, видя, что это похоже на слуховые гвозди на доске - это больно. Хотя нулевые макеты и setBounds() могут показаться новичкам Swing, как самый простой и лучший способ создания сложных графических интерфейсов, чем больше Swing GUI вы создадите более серьезные трудности, с которыми вы столкнетесь при их использовании. Они не будут изменять размеры ваших компонентов при изменении размера графического интерфейса, они являются королевской ведьмой для улучшения или поддержки, они полностью не выполняются при размещении в scrollpanes, они выглядят ужасно ужасно при просмотре на всех платформах или разрешениях экрана, отличных от исходного , Вместо этого вы захотите изучить и изучить менеджеров компоновки, а затем вложить JPanels, каждый из которых использует свой собственный менеджер компоновки для создания приятных и сложных графических интерфейсов, которые хорошо смотрятся на всех ОС.


Бокового вопрос номер два: ваш код не свинг нити безопасный, так как графический интерфейс свинга может быть очень хорошо уведомлен наблюдаемой от качелей события отправки потока или EDT. Хотя это вряд ли вызовет частые или серьезные проблемы с этой простой программой, в общем случае было бы лучше использовать SwingPropertyChangeSupport и PropertyChangeListeners, а не Observer/Observable, если сможете.


Следующая Side Issue
Это:

public class Controller extends Observable(){ 

не компилируется/кошерной Java. То же самое для дублирующих конструкторов без параметров для класса SecondWindow. Да, мы знаем, что вы пытаетесь сделать, но это достаточно сложно, чтобы понять чужой код, вы действительно не хотите, чтобы это стало сложнее, отправляя своего рода несовместимый код, поверьте мне.


Например, что-то просто можно было бы реализовать в Swing, используя PropertyChangeListeners, например, так:

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()); 
     } 
    } 
} 
Смежные вопросы