Gå til innhold

Er dette Model-View-Controller?


Anbefalte innlegg

Foreleseren min på NTNU kaller dette en "Full MVC"-implementasjon, er det egentlig det?

 

Person.java

 

package oving3;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class Person {

   public static final String NAME_PROPERTY = "name";

   public static final String DATEOFBIRTH_PROPERTY = "dateOfBirth";

   public static final String GENDER_PROPERTY = "gender";

   public static final String EMAIL_PROPERTY = "email";

   public static final String HEIGHT_PROPERTY = "height";

   private String name;

   private String dateOfBirth;

   private Gender gender;

   private String email;

   private int height;

   private PropertyChangeSupport pcs;

   public Person(String name) {
       this.name = name;
   }

   public void addPropertyChangeListener(PropertyChangeListener pcl) {
       if (pcs == null) {
           pcs = new PropertyChangeSupport(this);
       }
       pcs.addPropertyChangeListener(pcl);
   }

   public void removePropertyChangeListener(PropertyChangeListener pcl) {
       if (pcs != null) {
           pcs.removePropertyChangeListener(pcl);
       }
   }

   protected void firePropertyChangeEvent(String propertyName,
           Object oldValue, Object newValue) {
       if (pcs == null || oldValue == newValue
               || (oldValue != null && oldValue.equals(newValue))) {
           return;
       }
       pcs.firePropertyChange(propertyName, oldValue, newValue);
       System.out.println(propertyName + " changed : " + oldValue + " -> "
               + newValue);

   }

   public String getDateOfBirth() {
       return dateOfBirth;
   }

   public void setDateOfBirth(String dateOfBirth) {
       String oldDateOfBirth = this.dateOfBirth;
       this.dateOfBirth = dateOfBirth;
       firePropertyChangeEvent(Person.DATEOFBIRTH_PROPERTY, oldDateOfBirth,
               dateOfBirth);
   }

   public String getEmail() {
       return email;
   }

   public void setEmail(String email) {
       String oldEmail = this.email;
       this.email = email;
       firePropertyChangeEvent(Person.EMAIL_PROPERTY, oldEmail, email);
   }

   public int getHeight() {
       return height;
   }

   public void setHeight(int height) {
       int oldHeight = this.height;
       this.height = height;
       firePropertyChangeEvent(Person.HEIGHT_PROPERTY, oldHeight, height);
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       String oldName = this.name;
       this.name = name;
       firePropertyChangeEvent(Person.NAME_PROPERTY, oldName, name);
   }

   public Gender getGender() {
       return gender;
   }

   public void setGender(Gender gender) {
       Gender oldGender = this.gender;
       this.gender = gender;
       firePropertyChangeEvent(Person.GENDER_PROPERTY, oldGender, gender);
   }
}

 

 

PersonPanel.java

 

package oving3;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class PersonPanel extends JPanel implements ActionListener,
       FocusListener, PropertyChangeListener, ItemListener, ChangeListener {

private static final long serialVersionUID = 1L;

private Person model;

   private JTextField nameTextField;

   private JTextField dateOfBirthTextField;

   private JComboBox genderComboBox;

   private JTextField emailTextField;

   private JSlider heightSlider;

   public PersonPanel() {
       super();
       setBorder(BorderFactory.createCompoundBorder(BorderFactory
               .createEtchedBorder(), BorderFactory.createEmptyBorder(5, 5, 5,
               5)));

       nameTextField = new JTextField();
       nameTextField.setName("NamePropertyComponent");
       nameTextField.setColumns(25);

       emailTextField = new JTextField();
       emailTextField.setName("EmailPropertyComponent");
       emailTextField.setColumns(25);

       dateOfBirthTextField = new JTextField();
       dateOfBirthTextField.setName("DateOfBirthPropertyComponent");
       dateOfBirthTextField.setColumns(25);

       genderComboBox = new JComboBox();
       genderComboBox.setName("GenderPropertyComponent");
       genderComboBox.setModel(new DefaultComboBoxModel(Gender.values()));
       genderComboBox.setEditable(false);

       heightSlider = new JSlider(120, 220, 175);
       heightSlider.setName("HeightPropertyComponent");
       heightSlider.setMajorTickSpacing(10);
       heightSlider.setMinorTickSpacing(5);
       heightSlider.setPaintTicks(true);
       heightSlider.setPaintLabels(true);

       setLayout(new GridBagLayout());

       GridBagConstraints constraints = new GridBagConstraints();
       Insets insets = new Insets(2, 2, 2, 2);
       constraints.insets = insets;
       constraints.anchor = GridBagConstraints.LINE_START;

       constraints.gridy = 0;
       constraints.gridx = 0;
       constraints.gridheight = 1;
       constraints.gridwidth = 1;
       constraints.fill = GridBagConstraints.NONE;
       constraints.weightx = 0.0;
       add(new JLabel("Name: "), constraints);

       constraints.gridy = 0;
       constraints.gridx = 1;
       constraints.gridheight = 1;
       constraints.gridwidth = GridBagConstraints.REMAINDER;
       constraints.fill = GridBagConstraints.HORIZONTAL;
       constraints.weightx = 1.0;
       add(nameTextField, constraints);

       constraints.gridy = 1;
       constraints.gridx = 0;
       constraints.gridheight = 1;
       constraints.gridwidth = 1;
       constraints.fill = GridBagConstraints.NONE;
       constraints.weightx = 0.0;
       add(new JLabel("Email: "), constraints);

       constraints.gridy = 1;
       constraints.gridx = 1;
       constraints.gridheight = 1;
       constraints.gridwidth = GridBagConstraints.REMAINDER;
       constraints.fill = GridBagConstraints.HORIZONTAL;
       constraints.weightx = 1.0;
       add(emailTextField, constraints);

       constraints.gridy = 2;
       constraints.gridx = 0;
       constraints.gridheight = 1;
       constraints.gridwidth = 1;
       constraints.fill = GridBagConstraints.NONE;
       constraints.weightx = 0.0;
       add(new JLabel("Birthday: "), constraints);

       constraints.gridy = 2;
       constraints.gridx = 1;
       constraints.gridheight = 1;
       constraints.gridwidth = GridBagConstraints.REMAINDER;
       constraints.fill = GridBagConstraints.HORIZONTAL;
       constraints.weightx = 1.0;
       add(dateOfBirthTextField, constraints);

       constraints.gridy = 3;
       constraints.gridx = 0;
       constraints.gridheight = 1;
       constraints.gridwidth = 1;
       constraints.fill = GridBagConstraints.NONE;
       constraints.weightx = 0.0;
       add(new JLabel("Sex: "), constraints);

       constraints.gridy = 3;
       constraints.gridx = 1;
       constraints.gridheight = 1;
       constraints.gridwidth = GridBagConstraints.REMAINDER;
       constraints.fill = GridBagConstraints.NONE;
       constraints.weightx = 1.0;
       add(genderComboBox, constraints);

       constraints.gridy = 4;
       constraints.gridx = 0;
       constraints.gridheight = 1;
       constraints.gridwidth = 1;
       constraints.fill = GridBagConstraints.NONE;
       constraints.weightx = 0.0;
       add(new JLabel("Height: "), constraints);

       constraints.gridy = 4;
       constraints.gridx = 1;
       constraints.gridheight = 1;
       constraints.gridwidth = GridBagConstraints.REMAINDER;
       constraints.fill = GridBagConstraints.HORIZONTAL;
       constraints.weightx = 1.0;
       add(heightSlider, constraints);

       update();

       nameTextField.addActionListener(this);
       nameTextField.addFocusListener(this);
       emailTextField.addActionListener(this);
       emailTextField.addFocusListener(this);
       dateOfBirthTextField.addActionListener(this);
       dateOfBirthTextField.addFocusListener(this);
       genderComboBox.addItemListener(this);
       heightSlider.addChangeListener(this);
   }

   public void setModel(Person person) {
       if (model == person) {
           return;
       }
       if (model != null) {
           model.removePropertyChangeListener(this);
       }
       model = person;
       update();
       if (model != null) {
           model.addPropertyChangeListener(this);
       }
   }

   protected void update() {
       if (model != null) {
           updateComponent(null);
       } else {
           nameTextField.setText(null);
           dateOfBirthTextField.setText(null);
           genderComboBox.setSelectedItem(null);
           emailTextField.setText(null);
           heightSlider.setToolTipText(Integer.toString(0));
       }
   }

   protected void updateComponent(JComponent comp) {
       if (comp == null || comp == nameTextField) {
           nameTextField.setText(model.getName());
       }
       if (comp == null || comp == dateOfBirthTextField) {
           dateOfBirthTextField.setText(model.getDateOfBirth());
       }
       if (comp == null || comp == genderComboBox) {
           genderComboBox.setSelectedItem(model.getGender());
       }
       if (comp == null || comp == emailTextField) {
           emailTextField.setText(model.getEmail());
       }
       if (comp == null || comp == heightSlider) {
           int value = model.getHeight(), min = value, max = value;
           if (model.getGender() == Gender.female) {
               heightSlider.setMinimum(Math.min(140, min));
               heightSlider.setMaximum(Math.max(190, max));
           } else {
               heightSlider.setMinimum(Math.min(160, min));
               heightSlider.setMaximum(Math.max(210, max));
           }
           heightSlider.setValue(value);
           heightSlider.setToolTipText("Height is " + value);
       }
   }

   public void actionPerformed(ActionEvent e) {
       if (model == null) {
           return;
       }
       if (e.getSource() == nameTextField
               && !model.getName().equals(nameTextField.getText())) {
           model.setName(nameTextField.getText());
       } else if (e.getSource() == emailTextField) {
           model.setEmail(emailTextField.getText());
       } else if (e.getSource() == dateOfBirthTextField) {
           model.setDateOfBirth(dateOfBirthTextField.getText());
       }


   }

   public void focusGained(FocusEvent e) {
   }

   public void focusLost(FocusEvent e) {
       if (model == null) {
           return;
       }
       if (e.getSource() == nameTextField
               && !model.getName().equals(nameTextField.getText())) {
           model.setName(nameTextField.getText());
       } else if (e.getSource() == emailTextField 
       		&& !model.getEmail().equals(emailTextField.getText())) {
       	model.setEmail(emailTextField.getText());
       } else if (e.getSource() == dateOfBirthTextField 
       		&& !model.getDateOfBirth().equals(dateOfBirthTextField.getText())) {
       	model.setDateOfBirth(dateOfBirthTextField.getText());
       }

   }

   public void propertyChange(PropertyChangeEvent evt) {
       if (model == null) {
           return;
       }
       if (evt.getSource() == model) {
           modelPropertyChange(evt.getPropertyName());
       }
   }

   protected void modelPropertyChange(String propertyName) {
       if (Person.NAME_PROPERTY.equals(propertyName)) {
           updateComponent(nameTextField);
       } else if (Person.DATEOFBIRTH_PROPERTY.equals(propertyName)) {
           updateComponent(dateOfBirthTextField);
       } else if (Person.GENDER_PROPERTY.equals(propertyName)) {
           updateComponent(genderComboBox);
       } else if (Person.EMAIL_PROPERTY.equals(propertyName)) {
           updateComponent(emailTextField);
       } else if (Person.HEIGHT_PROPERTY.equals(propertyName)) {
           updateComponent(heightSlider);
       }

   }

   public void itemStateChanged(ItemEvent e) {
       if (model == null) {
           return;
       }
       if (e.getSource() == genderComboBox
               && !model.getGender().equals(genderComboBox.getSelectedItem())) {
           model.setGender((Gender) genderComboBox.getSelectedItem());
       }

   }

   public static Person createPerson(String name, String dateOfBirth, Gender gender,
           String email, int height) {
       Person person = new Person(name);
       person.setDateOfBirth(dateOfBirth);
       person.setGender(gender);
       person.setEmail(email);
       person.setHeight(height);
       return person;
   }

   public void stateChanged(ChangeEvent e) {
       if (model == null) {
           return;
       }
       if (e.getSource() == heightSlider
               && !heightSlider.getValueIsAdjusting()) {
           model.setHeight(heightSlider.getValue());
           heightSlider.setToolTipText(Integer.toString(heightSlider
                   .getValue()));
       }

   }

   public static void main(String[] args) throws InterruptedException {
       JFrame frame = new JFrame();
       PersonPanel panel = new PersonPanel();
       panel.setModel(createPerson("Rune Molden", "27.mai.1975", Gender.male,
               "[email protected]", 175));
       frame.setTitle(panel.getClass().getName());
       frame.setContentPane(panel);
       frame.pack();
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.setVisible(true);
       Thread.sleep(4000);
       panel.model.setName("Rolf Utgård");
       panel.model.setHeight(199);
   }
}

 

 

MVC skal vel ha en "controller"-klasse slik at ikke viewet manipulerer modellen direkte. Dette ligner vel mer på en Observer-implementasjon, eller har jeg misforstått helt hva MVC er?

Lenke til kommentar
Videoannonse
Annonse

Vel ut fra det jeg vet og så av koden virket det ikke som noen god MVC implementasjon.

 

MVC : Model–View–Controller. Så langt jeg ser er model ok men de to andre delene ser for meg blandet sammen om det er den metoden. Driver selv med å programmere noe som bruker MVC, men som eclipse plugin som bruker andre biblioteker.

 

Her er deler av et eksempel jeg fant, her må en sørge for at controlleren finner ut om modellen er forandret og så vil den oppdatere viewet.

 

Employe.java

 

package tutogef.model;		

public class Employe {		

private String prenom;	
private String name;	

public String getPrenom() {	
	return prenom;
}	

public void setPrenom(String prenom) {	
	this.prenom = prenom;
}	
public String getName() {	
	return name;
}	

public void setName(String name) {	
	this.name = name;
}	

}

 

EmployeFigure.java

 

package tutogef.figure;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Rectangle;

public class EmployeFigure extends Figure{

private Label labelPrenom = new Label();
private Label labelName = new Label();

public EmployeFigure() {
	XYLayout layout = new XYLayout();
	setLayoutManager(layout);

	labelPrenom.setForegroundColor(ColorConstants.black);
	add(labelPrenom, ToolbarLayout.ALIGN_CENTER);
	setConstraint(labelPrenom, new Rectangle(5, 5, -1, -1));

	labelName.setForegroundColor(ColorConstants.darkGray);
	add(labelName, ToolbarLayout.ALIGN_CENTER);
	setConstraint(labelName, new Rectangle(5, 17, -1, -1));

	setForegroundColor(ColorConstants.darkGray);
	setBackgroundColor(ColorConstants.lightGray);
	setBorder(new LineBorder(1));
	setOpaque(true);
}
public void setPrenom(String prenom) {
	labelPrenom.setText(prenom);
}
public void setName(String name) {
	labelName.setText(name);
}
public void setLayout(Rectangle rect) {
	getParent().setConstraint(this, rect);
}

}

 

EmployePart.java

 

package tutogef.part;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.IFigure;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;

import tutogef.figure.EmployeFigure;
import tutogef.model.Employe;
import tutogef.model.Node;

public class EmployePart extends AbstractGraphicalEditPart {

@Override
protected IFigure createFigure() {	
	IFigure figure = new EmployeFigure();
	return figure;
}

@Override
protected void createEditPolicies() {
	// TODO Auto-generated method stub

}	

protected void refreshVisuals(){
	EmployeFigure figure = (EmployeFigure)getFigure();
	Employe model = (Employe)getModel();
	figure.setLayout(model.getLayout());

	figure.setPrenom(model.getPrenom());
	figure.setName(model.getName());


}

public List<Node> getModelChildren() {
	return new ArrayList<Node>();
}

}

 

I tilegg så er det en factory som lager riktig control object til et model objekt og kobler dem sammen

 

AppEditPartFactory.java

 

package tutogef.part;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;

import tutogef.model.Employe;
import tutogef.model.Entreprise;
import tutogef.model.Service;

public class AppEditPartFactory implements EditPartFactory{

@Override
public EditPart createEditPart(EditPart context, Object model) {
	AbstractGraphicalEditPart part = null;

	if(model instanceof Entreprise) {
		part = new EntreprisePart();
	} else if (model instanceof Service) {
		part = new ServicePart();
	} else if (model instanceof Employe) {
		part = new EmployePart();
	}
	if(part != null){
		part.setModel(model);
	}
	return part;
}

}

 

Lenke til kommentar
  • 1 måned senere...

Det er kanskje greit å lese denne artikkelen:

http://java.sun.com/products/jfc/tsc/articles/architecture/

We quickly discovered that this split didn't work well in practical terms because the view and controller parts of a component required a tight coupling (for example, it was very difficult to write a generic controller that didn't know specifics about the view). So we collapsed these two entities into a single UI (user-interface) object, as shown in this diagram:

 

Mao, Swing er laget etter prinsippet at du har en Model og en View/Controller, veldig tilsvarende det du har med en Person og et PersonPanel.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...