2015-08-15 13 views
1

Я пытаюсь реализовать шаблон Observer с несколькими экземплярами JFrame. Однако, когда вызывается notifyObservers(), обновляется только последний экземпляр экземпляра JFrame.java.util.observer с несколькими JFrame

Это мой код:

Mall.java

import java.util.ArrayList; 
    import java.util.Observable; 

    public class Mall extends Observable{ 
     private ArrayList<String> stores; 

     public Mall(){ 
      stores = new ArrayList<String>(); 
     } 

     public void addNewStore(String store){ 
      stores.add(store); 
      System.out.println(store); 
      setChanged(); 
      notifyObservers(store); 
     } 

     public ArrayList<String> getStores(){ 
      return stores; 
     } 
    } 

CustomerFrame.java

public class CustomerFrame extends javax.swing.JFrame { 

     public CustomerFrame() { 
      initComponents(); 
     } 

     public CustomerFrame(Mall theMall) { 
      initComponents(); 
      MallObserver mallObs = new MallObserver(); 
      theMall.addObserver(mallObs); 

     } 

     private void initComponents() { 

      jScrollPane1 = new javax.swing.JScrollPane(); 
      jList1 = new javax.swing.JList(); 

      setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

      jList1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); 
      jScrollPane1.setViewportView(jList1); 

      javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
      getContentPane().setLayout(layout); 
      layout.setHorizontalGroup(
     layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addGroup(layout.createSequentialGroup() 
      .addContainerGap() 
      .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 249, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addContainerGap(141, Short.MAX_VALUE)) 
      ); 
      layout.setVerticalGroup(
     layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addGroup(layout.createSequentialGroup() 
      .addContainerGap() 
      .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 165, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addContainerGap(124, Short.MAX_VALUE)) 
      ); 

      pack(); 
     }     

     public static javax.swing.JList jList1; 
     private javax.swing.JScrollPane jScrollPane1;     
    } 

MallObserver.java

import java.util.Observable; 
    import java.util.Observer; 
    import javax.swing.DefaultListModel; 

    public class MallObserver implements Observer{ 

     private Mall mallUpdate; 

     @Override 
     public void update(Observable o, Object arg) { 
      mallUpdate = (Mall) o; 
      DefaultListModel listModel = new DefaultListModel(); 
      for(int i = 0; i < mallUpdate.getStores().size(); i++) 
       listModel.addElement(mallUpdate.getStores().get(i)); 
      CustomerFrame.jList1.setModel(listModel); 
     } 

    } 

AdminFrame.java

 public class AdminFrame extends javax.swing.JFrame { 

     Mall theMall; 

     public AdminFrame() { 
      initComponents(); 
      theMall = new Mall(); 
     } 
    @SuppressWarnings("unchecked")       
     private void initComponents() { 

      jTextField1 = new javax.swing.JTextField(); 
      jLabel1 = new javax.swing.JLabel(); 
      jButton1 = new javax.swing.JButton(); 
      jButton2 = new javax.swing.JButton(); 

      setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

      jTextField1.setText("jTextField1"); 

      jLabel1.setText("jLabel1"); 

      jButton1.setText("Add Store"); 
      jButton1.addActionListener(new java.awt.event.ActionListener() { 
       public void actionPerformed(java.awt.event.ActionEvent evt) { 
        jButton1ActionPerformed(evt); 
       } 
      }); 

      jButton2.setText("New Customer"); 
      jButton2.addActionListener(new java.awt.event.ActionListener() { 
       public void actionPerformed(java.awt.event.ActionEvent evt) { 
        jButton2ActionPerformed(evt); 
       } 
      }); 

      javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
      getContentPane().setLayout(layout); 
      layout.setHorizontalGroup(
     layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 
      .addContainerGap(143, Short.MAX_VALUE) 
      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
       .addComponent(jButton2) 
       .addComponent(jButton1) 
       .addGroup(layout.createSequentialGroup() 
        .addComponent(jLabel1) 
        .addGap(26, 26, 26) 
        .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) 
      .addGap(138, 138, 138)) 
      ); 
      layout.setVerticalGroup(
     layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addGroup(layout.createSequentialGroup() 
      .addGap(129, 129, 129) 
      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
       .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addComponent(jLabel1)) 
      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
      .addComponent(jButton1) 
      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 
      .addComponent(jButton2) 
      .addContainerGap(88, Short.MAX_VALUE)) 
      ); 

      pack(); 
     } 

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {           
      CustomerFrame newCust = new CustomerFrame(); 
      newCust.setVisible(true); 
     } 

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
      theMall.addNewStore(jTextField1.getText()); 
     } 

    public static void main(String args[]) { 

      try { 
       for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
        if ("Nimbus".equals(info.getName())) { 
       javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
         break; 
        } 
       } 
      } catch (ClassNotFoundException ex) { 
       java.util.logging.Logger.getLogger(AdminFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
      } catch (InstantiationException ex) { 
       java.util.logging.Logger.getLogger(AdminFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
      } catch (IllegalAccessException ex) { 
       java.util.logging.Logger.getLogger(AdminFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
      } catch (javax.swing.UnsupportedLookAndFeelException ex) { 
         java.util.logging.Logger.getLogger(AdminFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
        } 

    java.awt.EventQueue.invokeLater(new Runnable() { 
       public void run() { 
        new AdminFrame().setVisible(true); 
       } 
      }); 
     } 


     private javax.swing.JButton jButton1; 
     private javax.swing.JButton jButton2; 
     private javax.swing.JLabel jLabel1; 
     private javax.swing.JTextField jTextField1; 

    }     

Идея заключается в том, когда клиент входит в магазин, магазин будет открыт новый JFrame для клиента. Когда администратор добавит магазин, все JFrame CustomerFrame.java будут обновлены. Однако в моем случае только обновление CustomerFrame.java будет обновляться, а остальные остаются неизменными.

Проблема выше, может быть воспроизведен Открытие 2 новых клиентов и попытаться Добавить магазин в AdminFrame.java

Что здесь проблема?

+0

See (http://stackoverflow.com/q/9554636/418556) –

ответ

2

Вы не вызываете никаких методов на thisFrame из метода update(...) MallCustomer. Вместо того, чтобы устанавливать модель на storeList (откуда это происходит?), Дайте CustomerFrame общедоступный метод, например, вызванный setStoreListModel(ListModel listModel), который вы вызываете в update, передавая в storeModel.

т.е.

public class CustomerFrame extends javax.swing.JFrame { 
    privarte Mall theMall; 
    private JList storesList = new JList(); 

    public CustomerFrame(Customer customer, Mall theMall){ 
     MallCustomer mallObserver = new MallCustomer(this); 
     theMall.addObserver(mallObserver); 
    } 

    public setStoresListModel(ListModel listModel) { 
     storesList.setModel(listModel); 
    } 
} 

и

@Override 
public void update(Observable o, Object arg) { 
    mallUpdate = (Mall) o; 
    DefaultListModel storeModel = new DefaultListModel(); 

    //Stores update 
    for(int i = 0; i < mallUpdate.getStores().size();i++) { 
     storeModel.addElement(mallUpdate.getStores().get(i)); 
    } 
    // storesList.setModel(storeModel);//a JList variable 
    thisFrame.setStoresListModel(storeModel); 
}  

Примечание: Код не компилируется, ни протестированы


Редактировать

У вас есть несколько вопросов, которые я вижу:

  • Ваш JList не должен быть общедоступным или статическим. Сделайте это частным полем экземпляра.
  • Опять же (как я и предлагал), дайте клиенту окно общедоступного метода setListModel.
  • Приложение должно иметь только один основной JFrame, поэтому JFrame CustomerFrame не должен быть JFrame, а должен быть немодальным JDialog или, может быть, лучше JPanel, который может быть размещен где угодно - в собственном JDialog, в основной JFrame.
  • Передайте основной JFrame в свои JDialogs, чтобы диалоговое окно могло зарегистрировать родительский JFrame в его конструкторе супер.
  • Передайте экземпляр CustomerDialog в экземпляр MallObserver, а затем используйте его, чтобы установить поле внутри MallObserver.
  • В методе обновления создайте или обновите модель и вызовите `setListModel в экземпляре диалога клиента, который имеет MallObserver.
  • Создать торговый экземпляр до по телефону initComponents(). Таким образом, вы можете использовать тот же экземпляр Mall внутри ваших методов прослушивателя действий.
  • Nit-pick: при создании и публикации MCVE, избавиться от беспорядочного и отвлекающего сгенерированного кода NetBeans. Вместо этого публикуйте только простой код и простой графический интерфейс, который вы создали сами, подобно изменениям, которые я сделал ниже.
  • И вы, как MCVE, должны входить в один файл. Файл может иметь несколько классов, но нам будет легко разрезать и вставить в наши IDE, а затем запустить.

Например: [? Использование нескольких JFrames, хороший/плохой практики]

import java.util.ArrayList; 
import java.util.Observable; 
import java.util.Observer; 
import java.awt.event.*; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class AdminFrame extends javax.swing.JFrame { 

    private Mall theMall = new Mall(); //!! 

    public AdminFrame() { 
     initComponents(); 
     //!! theMall = new Mall(); 
    } 

    private void initComponents() { 

     jTextField1 = new javax.swing.JTextField(); 
     jLabel1 = new javax.swing.JLabel(); 
     addStoreBtn = new javax.swing.JButton(); 
     newCustBtn = new javax.swing.JButton(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

     jTextField1.setText("jTextField1"); 

     jLabel1.setText("jLabel1"); 

     addStoreBtn.setText("Add Store"); 
     addStoreBtn.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       theMall.addNewStore(jTextField1.getText()); 
      } 
     }); 
     addStoreBtn.setMnemonic(KeyEvent.VK_S); 

     newCustBtn.setText("New Customer"); 
     newCustBtn.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       // !! CustomerFrame newCust = new CustomerFrame(); 
       CustomerDialog newCust = new CustomerDialog(AdminFrame.this, theMall); 
       newCust.pack(); 
       newCust.setLocationByPlatform(true); 
       newCust.setVisible(true); 
      } 
     }); 
     newCustBtn.setMnemonic(KeyEvent.VK_C); 

     JPanel mainPanel = new JPanel(); 
     mainPanel.add(jLabel1); 
     mainPanel.add(jTextField1); 
     mainPanel.add(addStoreBtn); 
     mainPanel.add(newCustBtn); 

     add(mainPanel); 

     pack(); 
     setLocationRelativeTo(null); 
    } 

    public static void main(String args[]) { 

     java.awt.EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       new AdminFrame().setVisible(true); 
      } 
     }); 
    } 

    private javax.swing.JButton addStoreBtn; 
    private javax.swing.JButton newCustBtn; 
    private javax.swing.JLabel jLabel1; 
    private javax.swing.JTextField jTextField1; 

} 

class MallObserver implements Observer { 

    private Mall mallUpdate; 
    private CustomerDialog customerDialog; // !! 

    // !! 
    public MallObserver(CustomerDialog customerFrame) { 
     this.customerDialog = customerFrame; // !! 
    } 

    @Override 
    public void update(Observable o, Object arg) { 
     mallUpdate = (Mall) o; 
     DefaultListModel<String> listModel = new DefaultListModel<>(); 
     for (int i = 0; i < mallUpdate.getStores().size(); i++) { 
      listModel.addElement(mallUpdate.getStores().get(i)); 
     } 

     customerDialog.setListModel(listModel); 
    } 

} 

@SuppressWarnings("serial") 
class CustomerDialog extends JDialog { //!! 

    // !!!!!!! public CustomerFrame() { 
    // initComponents(); 
    // } 

    public void setListModel(ListModel<String> listModel) { 
     jList1.setModel(listModel); 
    } 

    public CustomerDialog(AdminFrame adminFrame, Mall theMall) { 
     super(adminFrame, "Customer Dialog", ModalityType.MODELESS); 
     initComponents(); 
     // !! MallObserver mallObs = new MallObserver(); 
     MallObserver mallObs = new MallObserver(this); // !! 
     theMall.addObserver(mallObs); 
    } 

    private void initComponents() { 

     jScrollPane1 = new javax.swing.JScrollPane(); 
     jList1 = new JList<>(); 
     jList1.setPrototypeCellValue("        "); 
     jList1.setVisibleRowCount(15); 

     setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); 

     jList1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); 
     jScrollPane1.setViewportView(jList1); 

     add(jScrollPane1); 

     pack(); 
    } 

    // public static javax.swing.JList jList1; 
    private JList<String> jList1; 
    private JScrollPane jScrollPane1; 
} 

class Mall extends Observable { 
    private ArrayList<String> stores; 

    public Mall() { 
     stores = new ArrayList<String>(); 
    } 

    public void addNewStore(String store) { 
     stores.add(store); 
     setChanged(); 
     notifyObservers(store); 
    } 

    public ArrayList<String> getStores() { 
     return stores; 
    } 


} 
+0

К сожалению, я скопировал неправильный код, отредактировал его. –

+1

@RyanLiew: Ваш незавершенный вопрос был изменен, теперь аннулируем мой ответ. В будущем, пожалуйста, задайте полные вопросы, включая публикацию [mcve], чтобы мы не тратили свое время. Пожалуйста, прочитайте ссылку [mcve], чтобы вы могли ее создать, опубликовать и задать свой вопрос. –

+0

Так жаль ... Я редактировал вопрос с кодами, которые будут воспроизводить проблему. –