简体   繁体   中英

Duplicated values and some methods automatically getting called in MVC pattern

Please have a look at the following code

package test;


import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

public class MainGui {
   public MainGui() {
      new WizardPanel().setVisible(true);
   }

   public static void main(String[] args) {
      try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
         new MainGui();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

class WizardPanel extends JDialog {
   private JPanel cardPanel, buttonPanel;
   private JButton next;
   private CardLayout c1;
   private SimpleModel simpleModel = new SimpleModel();

   private FileSelector fileSelector;
   private DelemeterSelector delemeterSelector;

   public WizardPanel() {
      fileSelector = FileSelector.getInstance();
      delemeterSelector = DelemeterSelector.getInstance();

      fileSelector.setModel(simpleModel); //!!
      delemeterSelector.setModel(simpleModel); //!!

      cardPanel = new JPanel();
      c1 = new CardLayout();
      cardPanel.setLayout(c1);

      cardPanel.add(fileSelector, "1");
      cardPanel.add(delemeterSelector, "2");

      c1.show(cardPanel, "1");

      buttonPanel = new JPanel();
      buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));

      next = new JButton("Next");
      next.addActionListener(new WizardPanel.NextButtonAction()); 

      buttonPanel.add(next);

      // Creating the GUI
      this.setLayout(new BorderLayout());
      this.add(cardPanel, "Center");
      this.add(buttonPanel, "South");

      this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      this.setResizable(true);
      this.pack();
      this.setVisible(true);

   }

   private class NextButtonAction implements ActionListener {
      public void actionPerformed(ActionEvent ae) {

         // c1.show(cardPanel, "2");
         c1.next(cardPanel); //!!

      }
   }
}

class FileSelector extends JPanel {
   private JLabel fileName, description;
   private JTextField fileTxt;
   private JButton browse;

   private GridBagLayout gbl;
   private GridBagConstraints gbc;
   private SimpleModel simpleModel;

   private static FileSelector instance = null;

   private FileSelector() {
      // Intializing instance variables
      fileName = new JLabel("File Name: ");
      description = new JLabel("Specify the source of the data");

      fileTxt = new JTextField(10);

      browse = new JButton("Browse");
      browse.addActionListener(new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            if (simpleModel != null) {
               simpleModel.setFileText(fileTxt.getText());
            }
         }
      });

      gbl = new GridBagLayout();
      gbc = new GridBagConstraints();

      // Creating GUI
      this.setLayout(new GridLayout(2,1));

      this.add(description);
      this.add(locationPanel());


      this.setBorder(BorderFactory.createEmptyBorder());
   }

   public void setModel(SimpleModel simpleModel) {
      this.simpleModel = simpleModel;
   }

   private JPanel locationPanel() {
      JPanel panel = new JPanel();
      panel.setLayout(new FlowLayout());

      panel.add(fileName);
      panel.add(fileTxt);
      panel.add(browse);

      return panel;
   }

   public static FileSelector getInstance() {
      if (instance == null) {
         instance = new FileSelector();
      }

      return instance;
   }
}

class DelemeterSelector extends JPanel {
   private JLabel description;
   private JRadioButton tabBtn, semicolanBtn, commaBtn, spaceBtn;
   private JTextArea txtArea;
   private JScrollPane scroll;
   private ButtonGroup btnGroup;

   private GridBagLayout gbl;
   private GridBagConstraints gbc;
   private SimpleModel simpleModel;

   private String str;

   private static DelemeterSelector instance = null;

   private DelemeterSelector() {
      description = new JLabel(
            "What delemeter separates your fields? Select the appropreiate delemeter");

      tabBtn = new JRadioButton("Tab");
      tabBtn.addItemListener(new RadioAction());
      semicolanBtn = new JRadioButton("Semicolan");
      semicolanBtn.addItemListener(new RadioAction());
      commaBtn = new JRadioButton("Comma");
      commaBtn.addItemListener(new RadioAction());
      spaceBtn = new JRadioButton("Space");
      spaceBtn.addItemListener(new RadioAction());

      btnGroup = new ButtonGroup();
      btnGroup.add(tabBtn);
      btnGroup.add(semicolanBtn);
      btnGroup.add(commaBtn);
      btnGroup.add(spaceBtn);

      txtArea = new JTextArea(20, 70);

      scroll = new JScrollPane(txtArea);

      gbl = new GridBagLayout();
      gbc = new GridBagConstraints();

      this.setLayout(new GridLayout(3,1));

      // Creating the GUI
      this.add(description);
      this.add(radioPanel());
      this.add(scroll);      
   }

   private JPanel radioPanel() {
      JPanel panel = new JPanel();
      panel.setLayout(new FlowLayout());

      panel.add(tabBtn);
      panel.add(semicolanBtn);
      panel.add(commaBtn);
      panel.add(spaceBtn);

      panel.setBorder(BorderFactory
            .createTitledBorder("Choose the Delimeter that seperates your fields"));

      return panel;
   }

   //!!
   public void setModel(final SimpleModel simpleModel) {
      this.simpleModel = simpleModel;
      simpleModel.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent evt) {
            txtArea.append("File Text: " + simpleModel.getFileText() + "\n");            
         }
      });
   }

   public static DelemeterSelector getInstance() {
      if (instance == null) {
         instance = new DelemeterSelector();
      }

      return instance;
   }

   private class RadioAction implements ItemListener
   {
       public void itemStateChanged(ItemEvent ae)
       {
           if(ae.getStateChange()==ItemEvent.SELECTED){
           if(ae.getSource().equals(commaBtn))
           {
               str = ".";
           }
           else if(ae.getSource().equals(spaceBtn))
           {
               str = " ";
           }
           else if(ae.getSource().equals(semicolanBtn))
           {
               str = ";";
           }

           simpleModel.setDelemeter(str);}
       }
   }
}

class SimpleModel {
   public static final String FILE_TEXT = "file text";
   public static final String FILE_DELEMETER = "dELEMETERtext";
   private SwingPropertyChangeSupport pcSupport = 
      new SwingPropertyChangeSupport(this);
   private String fileText;
   private String str;

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(listener);
   }

   public void setFileText(String fileText) {
      String oldValue = this.fileText;
      String newValue = fileText;
      this.fileText = fileText;
      pcSupport.firePropertyChange(FILE_TEXT, oldValue , newValue);

   }

   public String getFileText() {
      return fileText;
   }

   public void setDelemeter(String str)
   {
       String oldValue = this.str;
      String newValue = str;
      this.str = str;
      pcSupport.firePropertyChange(FILE_DELEMETER, oldValue , newValue);

      System.out.println(str);
   }

}

This code uses MVC design patters. It records the text of JTextField from the first sliding window. When user moves to the second window, it displays the text which you typed in first window, in JTextArea.

Now, click on any of the radio buttons allocated there. You will see that JTextArea is displaying the data which was typed in first window, even I am not calling that getFileText() method there. It seems like it is keep on calling getFileText() method and keep on updating the JTextArea whenever I click on a JRadioButton. But inside JRadioButton's action class, I never called for such an action, I just set the delemeter!!

why this errors are happening? Please help!

Your problem is this line:

  simpleModel.addPropertyChangeListener(new PropertyChangeListener() {

     @Override
     public void propertyChange(PropertyChangeEvent evt) {
        txtArea.append("File Text: " + simpleModel.getFileText() + "\n");            
     }
  });

In conjunction with these:

 public void setFileText(String fileText) {
      String oldValue = this.fileText;
      String newValue = fileText;
      this.fileText = fileText;
      pcSupport.firePropertyChange(FILE_TEXT, oldValue , newValue);

   }

   public void setDelemeter(String str)
   {
       String oldValue = this.str;
      String newValue = str;
      this.str = str;
      pcSupport.firePropertyChange(FILE_DELEMETER, oldValue , newValue);

      System.out.println(str);
   }

You're not inspecting the name of the property getting fired (in the first set of code), so when setFileText or setDelemeter is called, the firePropertyChange will execute and display the file name.

The easiest solution would be to check the name of the property like so:

  simpleModel.addPropertyChangeListener(new PropertyChangeListener() {

     @Override
     public void propertyChange(PropertyChangeEvent evt) {
        if(evt.getPropertyName().equale(SimpleModel.FILE_TEXT)
            txtArea.append("File Text: " + simpleModel.getFileText() + "\n");            
     }
  });

I did not went over all the code, but note that you get two events when changing the radiobuttons. I for the deselection of the first button, and for the selection of the new button.

You can check for the state in the ItemEvent . See ItemEvent#getStateChange and the ItemEvent.SELECTED and ItemEvent.DESELECTED constants.

Note that if you only want to trigger the action when the button gets selected, it is easier to attach an ActionListener to the radio button. This is illustrated in the radio button tutorial .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM