I am trying to implement Observer pattern with multiple JFrame instances. However, when notifyObservers()
is called, only the last instantiated JFrame instance is updated.
This is my code:
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;
}
The idea is, when a customer enters the store, the store will open up a new JFrame for the customer. When admin adds a store, all the JFrame CustomerFrame.java
will have their list item updated. However, in my case, only the CustomerFrame.java
that is last instantiated will get the update while the others remains the same.
The problem above can be reproduced by Opening 2 New Customer and try to Add Store at AdminFrame.java
What is the problem here?