Implementierung eines Einheit-Wandlers in java gemäß dem Controller-View-Model Approach

Dieser Einheits-Wandler wird mit 4 Klassen realisiert. Dazu dienen jeweils eine Klasse dem View-, Controller-, Model- und Main-Teil gemäß dem CVM-Approach.

Es folgen die vier separaten Klassen als Java Quellcode

Erste Klasse – Modelteil / Strukturteil 

package model;

/**
 * Diese Klasse repräsentiert eine Längeneinheit
 * @author LSF
 * @version 14.05.2013
 */

public class UnitOfLength implements Comparable<UnitOfLength> {
    private String name;
    private double inMm;

    /**
     * Konstruktor, dem ein Name und der Umrechnungsfaktor zu Millimetern übergeben wird
     * @param name
     *            Name der Längeneinheit
     * @param inMm
     *            Umrechnungsfaktor zu Millimeter
     */
    public UnitOfLength(String name, double inMm) {
    	super();
    	this.name = name;
    	this.inMm = inMm;
    }

    /**
     * Liefert den Namen der Längeneinheit zurück
     * @return Name der Längeneinheit
     */
    public String getName() {
    	return name;
    }

    /**
     * Legt den Namen der Längeneinheit fest
     * @param name
     *            einzustellender Name
     */
    public void setName(String name) {
    	this.name = name;
    }

    /**
     * Liefert den Umrechnungsfaktor zur¸ck
     * @return Umrechnungsfaktor
     */
    public double getInMm() {
    	return inMm;
    }

    /**
     * Setzt den Umrechnungsfaktor
     * @param inMm
     *            Umrechnungsfaktor
     */
    public void setInMm(double inMm) {
    	this.inMm = inMm;
    }

    @Override
    public int compareTo(UnitOfLength unit) {
    	return this.toString().compareTo(unit.toString()); // Sortiert alphabetisch
    }

    /*
     * (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    public String toString() {
    	return name;
    }
}

Der Viewteil

package view;

import java.awt.*;
import java.util.*;

import javax.swing.*;
import javax.swing.border.*;

import java.text.*;

import controller.UmrechnerController;

import model.UnitOfLength;

import model.*;

/**
 * Diese Klasse repräsentiert ein Fenster, mit dem Längeneinheiten ineinander umgerechnet werden
 * können
 * 
 * @author LSF
 * @versino 14.05.2013
 * 
 */
@SuppressWarnings("serial")
public class UmrechnerView extends JFrame {

    //-----------------------declarations-----------------------------------------------------------------
	 private UmrechnerController controller;
	
	private Container c = getContentPane();
    
    private JComboBox comboBoxLinks, comboBoxRechts;
    private JTextField textFeldLinks, textFeldRechts; // textFeldX.setEnabled(boolean b); -> via default b = true! 
    private JPanel panel1, panel2, panel3, panel4;
    private JButton unitButton, calculateButton;
    private Checkbox checkboxOben, checkboxUnten;
    private JRadioButton radioButtonOben, radioButtonUnten;
    
    private UnitOfLength [] unitsArray;
    private UnitOfLength dummy;
    
    private int zaehler;
    
    private boolean fehlerIgnorieren = false;  // setting default preference 
    private boolean textfeldLinksAktiv = true; // setting default preference
    
    /**
     * Konstruktor der Klasse UmrechnerView
     * @param units
     *            Set von Einheiten-Objekten (UnitOfLength), die berücksichtigt werden sollen
     */
    public UmrechnerView(TreeSet<UnitOfLength> units) {
    //--------------------setting layout of top container to 4 rows and 1 column--------------------------
    	c.setLayout(new GridLayout(4,1));
    
    //--------------------creating panel 1, setting layout and inserting 2 light weight text fields-------
    	panel1 = new JPanel(new GridLayout(1,2,5,0));
    	textFeldLinks = new JTextField();
    	textFeldLinks.setEnabled(this.textfeldLinksAktiv);
    	textFeldRechts = new JTextField();
    	textFeldRechts.setEnabled(!this.textfeldLinksAktiv); //gray out right text field as default preference
    	panel1.add(textFeldLinks);
    	panel1.add(textFeldRechts);
    	
    //--------------------creating panel 2, setting layout, adding combo box and buttons as well as frame-
    	panel2 = new JPanel(new GridLayout(1,3,2,0));
    	panel2.setBorder(new TitledBorder(null , "Umrechnung", TitledBorder.LEADING, TitledBorder.TOP, null , null));
    	
    	zaehler = 0;
    	unitsArray = new UnitOfLength[units.size()]; 					//array as big as it has to be
    	
    	for (Iterator i = units.iterator(); i.hasNext(); zaehler++) {	//filling array with Units of Length
			dummy = (UnitOfLength) i.next();
			unitsArray[zaehler] = dummy;
		}
    	
    	comboBoxLinks = new JComboBox(unitsArray);
    	comboBoxRechts = new JComboBox(unitsArray); 					//EVTL.: comboBoxLinks.setSelectedItem(anObject);
    	
    	unitButton = new JButton(">"); 									// ">" as default -> has to change by event
    	
    	panel2.add(comboBoxLinks);										//part adding to panel 2
    	panel2.add(unitButton);
    	panel2.add(comboBoxRechts);
    	
    //---------------------creating panel 3, setting layout, adding check buttons and radio buttons--------
    	panel3 = new JPanel(new GridLayout(2,2));
    	panel3.setBorder(new TitledBorder(null , "Einstellungen", TitledBorder.LEADING, TitledBorder.TOP, null , null));
    	
    	checkboxOben = new Checkbox("Tausendertrennzeichen");
    	checkboxUnten = new Checkbox("Fehler ignorieren");
    	radioButtonOben = new JRadioButton("Ergebnis grün");
    	radioButtonUnten = new JRadioButton("Ergebnis rot");
    	
    	panel3.add(checkboxOben);
    	panel3.add(radioButtonOben);
    	panel3.add(checkboxUnten);
    	panel3.add(radioButtonUnten);
    	
    //----------------------creating panel 4, setting layout, adding button---------------------------------
    	panel4 = new JPanel(new GridLayout(1,1));
    	
    	calculateButton = new JButton("Berechnen");
    	
    	panel4.add(calculateButton);
    	
    //----------------------filling content pane------------------------------------------------------------
    	c.add(panel1);
    	c.add(panel2);
    	c.add(panel3);
    	c.add(panel4);
    
    //----------------------set title of content pane (JFrame)----------------------------------------------
    	this.setTitle("Umrechner");
    	
    //----------------------set size of content pane--------------------------------------------------------
    	this.setSize(400,400);
    	
    //----------------------set close operation for content frame (JFrame)----------------------------------
    	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    /**
     * Setzt den für die View zuständigen Controller
     * @param controller
     *            zu setzender Controller
     */
    public void setController(UmrechnerController controller) {
    	this.controller = controller;
    	checkboxUnten.addItemListener(this.controller.getCheckboxListener());
    	unitButton.addActionListener(this.controller.getUnitListener());
    	calculateButton.addActionListener(this.controller.getCalculateListener());
    }
    
    //------------whether exceptions are being ignored or not is set by this method------------------------params from controller
    public void setFehlerIgnorieren(boolean b){
    	this.fehlerIgnorieren = b;
    }
    
    //-------------are exceptions being ignored or not?-----------------------------------------------------
    public boolean getFehlerIgnorieren(){
    	return this.fehlerIgnorieren;
    }
    
    //-------------does the user want exceptions to be ignored?---------------------------------------------
    public boolean getCheckboxUntenState(){
    	return checkboxUnten.getState();
    }
    
    //----------which text field should be enabled now?-----------------------------------------------------params from controller
    public void setTextfeldLinksAktiv(boolean b){
    	this.textfeldLinksAktiv = b;
    	this.textFeldLinks.setEnabled(b);
    	this.textFeldRechts.setEnabled(!b);
    }
    
    //----------which text field is enabled now?------------------------------------------------------------
    public boolean getTextfeldLinksAktiv(){
    	return this.textfeldLinksAktiv;
    }
    
    //---------return current frame as a container to the controller----------------------------------------
    public Container getViewContainer(){
    	return this.c;
    }
    
    //---------returns the current entry in the activated text field to the controller----------------------
    public String getAktuellenTextfeldEintrag(){
    	if(this.textfeldLinksAktiv){
    		return textFeldLinks.getText();
    	}else{
    		return textFeldRechts.getText();
    	}
    }
    
    //----------prints out the result of the transformation into the inactive text field--------------------params from controller
    public void printBerechnung(double d, DecimalFormat f){
    	//String.format("%1$,.2f",d);
    	if(this.textfeldLinksAktiv){
    		this.textFeldRechts.setText(f.format(d));
    	}else{
    		this.textFeldLinks.setText(f.format(d));
    	}
    }
    
    //-----------if exceptions are ignored this method just copies an pastes--------------------------------params from controller
    public void printBerechnung(String s){
    	if(this.textfeldLinksAktiv){
    		this.textFeldRechts.setText(s);
    	}else{
    		this.textFeldLinks.setText(s);
    	}
    }
    
    //-----------this method is used by controller to transform into desired unit----------------------------
    public UnitOfLength getComboObjektLinks(){
    	return (UnitOfLength) this.comboBoxLinks.getSelectedItem();
    }
    
    //-----------this method is used by controller to transform into desired unit----------------------------
    public UnitOfLength getComboObjektRechts(){
    	return (UnitOfLength) this.comboBoxRechts.getSelectedItem();
    }
    
    //-----------if unit button is pressed the arrow will change direction-----------------------------------params from controller
    public void setUnitButtonText(String s){
    	this.unitButton.setText(s);
    }
}

Der Controllerteil


package controller;

import java.awt.event.*;
import java.text.*; 						//gives access to DecimalFormat class
import java.util.*;

import javax.swing.*;

import view.UmrechnerView;

//import model.UnitOfLength;


/**
 * Die Klasse UmrechnerController kümmert sich um die Verarbeitung von Benutzereingaben im
 * zugehörigen View
 * @author LSF
 * @version 14.05.2013
 */
public class UmrechnerController {

    private UmrechnerView view; 			// letting reference point at our view object (container)

    /**
     * Erzeugt ein neues Objekt der inneren Klasse UnitListener und gibt es zurück
     * @return neues UnitListener-Objekt
     */
    public UnitListener getUnitListener() {
    	return new UnitListener();
    }

    /**
     * Erzeugt ein neues Objekt der inneren Klasse CalculateListener und gibt es zurück
     * @return neues CalculateListener-Objekt
     */
    public CalculateListener getCalculateListener() {
    	return new CalculateListener();
    }
    
    /**
     * Erzeugt ein neues Objekt der inneren Klasse CheckboxListener und gibt es zurück
     * @return neues CalculateListener-Objekt
     */
    public CheckboxListener getCheckboxListener(){
    	return new CheckboxListener();
    }

    /**
     * Setzt die vom Controller zu verwaltende View
     * @param view
     *            zu verwaltende View
     */
    public void setView(UmrechnerView view) {
    	this.view = view;
    	
    	// !!!! INITIALIZATION HAS BEEN REALIZED WHITING THE VIEW PART !!!!
    }

    /**
     * Diese innere Klasse implementiert das ActionListener-Interface, kann also verwendet werden,
     * um Benutzerinteraktion mit dem GUI zu verarbeiten. Sie soll sich um Ereignisse des
     * unitButtons k¸mmern
     * 
     * @author LSF
     * @version 14.05.2013
     * 
     */
    class UnitListener implements ActionListener {
    
    //-------------this method makes the direction of the arrow change as well as the direction of------------
    //-------------transformation is being changed by this method---------------------------------------------
	@Override
	public void actionPerformed(ActionEvent e) {
	    
		//---------negation principle - current activated text field is grayed out and other one is activated-
		if(view.getTextfeldLinksAktiv()){
			view.setUnitButtonText("<");
			view.setTextfeldLinksAktiv(false);
		}else if(!view.getTextfeldLinksAktiv()){
			view.setUnitButtonText(">");
			view.setTextfeldLinksAktiv(true);
		}	
	}
    }

    /**
     * Diese innere Klasse implementiert das ActionListener-Interface, kann also verwendet werden,
     * um Benutzerinteraktion mit dem GUI zu verarbeiten. Sie soll sich um Ereignisse des
     * calculateButtons k¸mmern
     * @author LSF
     * @version 14.05.2013
     */
    class CalculateListener implements ActionListener {

    //--------------when user presses the calculate button, he'll get what (s)he wants-----------------------
	@Override
	public void actionPerformed(ActionEvent e) {
	   //-----------exceptions are either ignored or not -> exception handling on demand---------------------
	   try{
		   
		   DecimalFormat ausgabeFormat = new DecimalFormat("#,###,###,###,###.000");
		   NumberFormat format = NumberFormat.getInstance(Locale.GERMANY);
		   
		   String eingabeString = view.getAktuellenTextfeldEintrag();
		   
		   if(view.getTextfeldLinksAktiv()){ 
			   
			   Number number = format.parse(eingabeString); //We need Double, not Number -> excplicit typecasting
			   double eingabeDouble = number.doubleValue();
			   
			   //double eingabeDouble = Double.parseDouble(eingabeString);
			   
			   double gewaehlteInputEinheit = view.getComboObjektLinks().getInMm();
			   double gewaehlteOutputEinheit = view.getComboObjektRechts().getInMm();
			   
			   double ausgabeDouble = (eingabeDouble*gewaehlteInputEinheit)/gewaehlteOutputEinheit;
			   
			   view.printBerechnung(ausgabeDouble, ausgabeFormat);
			   
		   }else if(!view.getTextfeldLinksAktiv()){
			   
			   Number number = format.parse(eingabeString); //We need Double, not Number -> excplicit typecasting
			   double eingabeDouble = number.doubleValue();
			   
			   //double eingabeDouble = Double.parseDouble(eingabeString);
			   
			   double gewaehlteInputEinheit = view.getComboObjektRechts().getInMm();
			   double gewaehlteOutputEinheit = view.getComboObjektLinks().getInMm();
			   
			   double ausgabeDouble = (eingabeDouble*gewaehlteInputEinheit)/gewaehlteOutputEinheit;
			   
			   view.printBerechnung(ausgabeDouble, ausgabeFormat);
		   }
	   }catch(NumberFormatException excpt1){
		   if(view.getFehlerIgnorieren()){
			   String eingabeString = view.getAktuellenTextfeldEintrag();
			   view.printBerechnung(eingabeString);
		   }else{
			  JOptionPane.showMessageDialog(view.getViewContainer(),"Diese Eingabe ist nicht gültig."); 
		   }
	   }catch(Exception excpt2){
		   
		   //-----------THIS PART IS NOT PERFECT YET------------------------------------------------------------
		   if(view.getFehlerIgnorieren()){
			   String eingabeString = view.getAktuellenTextfeldEintrag();
			   view.printBerechnung(eingabeString);
		   }else{
			  JOptionPane.showMessageDialog(view.getViewContainer(),"Diese Eingabe ist nicht gültig.","Eingabefehler", 1);
		   }
	   }
		
	}
    }
    
    //----------------------setting preferences: should error be ignored ot not?--------------------------------
    class CheckboxListener implements ItemListener{
    	@Override
    	public void itemStateChanged(ItemEvent e){
    		view.setFehlerIgnorieren(view.getCheckboxUntenState());
    	}
    }

}

Der Mainteil mit Mainmethode


package main;

import java.util.*;

import view.UmrechnerView;

import controller.UmrechnerController;

import model.UnitOfLength;


/**
 * Diese KLasse enth‰lt die main-Methode, aus der heraus das anzuzeigende Fenster und der Controller
 * erzeugt wird und die beiden miteinander bekannt gemacht werden
 * 
 * @author LSF
 * @version 14.05.2013
 * 
 */
public class UmrechnerMain {
    private static TreeSet<UnitOfLength> units;
    private static UmrechnerController controller;
    private static UmrechnerView view;

    /**
     * Main-Methode der Klasse
     * 
     * @param args
     *            Kommandozeilenparameter
     */
    public static void main(String[] args) {
	// Erzeuge eine Menge des Typs UnitOfLength
	units = new TreeSet<UnitOfLength>();
	// Fülle die Menge mit einigen Einheiten
	units.add(new UnitOfLength("Millimeter", 1));
	units.add(new UnitOfLength("Zentimeter", 10));
	units.add(new UnitOfLength("Meter", 1000));
	units.add(new UnitOfLength("Kilometer", 1000000));
	units.add(new UnitOfLength("Zoll", 25.4));
	units.add(new UnitOfLength("Fuß", 304.8));
	units.add(new UnitOfLength("Meile", 160900));
	units.add(new UnitOfLength("Seemeile", 185200));
	units.add(new UnitOfLength("Yard", 91.4));

	// Erzeuge einen Controller des Typs UmrechnerController
	controller = new UmrechnerController();

	// Erzeuge ein Fenster des Typs UmrechnerView
	view = new UmrechnerView(units);

	// Macht beide miteinander bekannt
	view.setController(controller);
	controller.setView(view);

	// Macht das Fenster sichtbar
	view.setVisible(true);

    }

}