f27sb2 software development 2 lecture 8: state diagram & gui example

46
F27SB2 Software Development 2 Lecture 8: State Diagram & GUI Example

Upload: oliver-lee

Post on 24-Dec-2015

223 views

Category:

Documents


2 download

TRANSCRIPT

F27SB2 Software Development 2

Lecture 8: State Diagram & GUI Example

Overview

• software address book• each entry consists of:– name– street– town– postcode– telephone number– email address

Overview

• load entries from file• save entries to file• controls to:– move forwards/backwards through entries– add new entry– delete entry– change entry– quit

Overview

inspect/modify

extend

NEW/clear data fields

ADD/insert new entry

CHANGE/modify entry;update display

UP;DOWN/update display

.../load file; display first entry

QUIT/update file

Design

• suggests:– JButtons for controls– JLabels for headings/prompts– JTextFields for changeable details

• separate JPanels for controls & details– may want to vary number of controls or details

Design

NEW

ADD

CHANGE

UP

DOWN

QUIT

name

street

town

postcode

phone

email

JFrame

JPanel JPanel

JButtons JLabels JTextFields

Entry representation

• represent entry within program as a class• 6 String fields• use individual variables?• advantage– can see which field is which

• disadvantage– need lots of individual assignments/accesses– might want to add fields– e.g. given/family names; country

Entry representation

• use array of string to hold details for each entry

• advantage– manipulate with for loops

• disadvantage– may forget which array element corresponds to

which field– does this matter?

Entry representationclass Entry{ String [] details; final int MAXDETAILS = 6;  public Entry(String [] newdetails) { details = new String[MAXDETAILS]; for(int i=0;i<MAXDETAILS;i++) details[i]=newdetails[i]; }

Entry representation

• outside program, keep Entrys in a text file• save each Entry to file when program ends public void writeEntry(PrintWriter file) { for(int i=0;i<MAXDETAILS;i++) file.println(details[i]); }}

Entry representation

• within program, hold Entrys in an arrayclass Address extends JFrame implements ActionListener{ ... Entry [] entries; int entryno; final int MAXENTRIES = 100;

• identify file final String addressbook = "addressbook.txt";

Entry representation

• load array from file when program starts void readEntries() throws IOException { BufferedReader file; entries = new Entry[MAXENTRIES]; entryno=0; String [] details = new String[MAXDETAILS];

• open file try { file = new BufferedReader (new FileReader(addressbook)); } catch(FileNotFoundException e){ return; }

Entry representation

• read 1st line from file => name for 1st Entry String line = file.readLine();

• loop until file empty while(line!=null) {

Entry representation

• program will check for space in array before additions using New

• however, user may extend text file by hand outside program

if(entryno==MAXENTRIES) { System. out.println("More than "+MAXENTRIES+ " entries."); System.exit(0); }

Entry representation

• set up name, read rest of details, build new Entry and add to array

details[0]=line; for(int i=1;i<MAXDETAILS;i++) details[i]=file.readLine(); entries[entryno]=new Entry(details); entryno++;

Entry representation

• try to read next line of file => name for next Entry

line = file.readLine(); } 

• close file at end

file.close(); ... }

• not quite enough for readEntries...

Interface & Initialisation

• require:– JButton for each control action• array of JButton

– text for JButtons• array of String

class Address extends JFrame implements ActionListener{ JButton [] actions; String [] actionText = {“New”,”Add”,”Change”,”Delete”, “Forward”,”Back”,”Quit”}; final int MAXACTIONS = 7;

Interface & Initialisation

• NB need to remember JButton map– actions[0] => New– actions[1] => Add– actions[2] => Change– actions[3] => Delete– actions[4] => Forward– actions[5] => Back– actions[6] => Quit

Interface & Initialisation

• JLabels for field titles– array of JLabel

• text for JLabel – array of String

JLabel [] headings; String [] text ={“Name”,”Street”,”Town”,”Postcode”, “Telephone”,”Email”};

Interface & Initialisation

• JTextFields for modifiable field details– array of JTextField

JTextField [] details; final int MAXDETAILS = 6;

• JPanels for Entry on interface and controls

JPanel entry,controls;

Interface & Initialisation

• methods to initialise JLabels, JButtons and JTextFields:

JTextField setupTextField(String s,Container c) { JTextField t = new JTextField(s); t.setFont(new Font(“Sansserif”,Font.PLAIN,18)); t.setBackground(Color.white); c.add(t); t.addActionListener(this); return t; }

JButton setupButton(String s,Container c) { JButton b = new JButton(s); b.setFont(new Font(“Sansserif”,Font.PLAIN,18)); b.setBackground(Color.white); c.add(b); b.addActionListener(this); return b; } JLabel setupLabel(String s,Container c) { JLabel l = new JLabel(s,JLabel.CENTER); l.setFont(new Font(“Sansserif”,Font.PLAIN,18)); l.setBackground(Color.white); c.add(l); return l; }

Interface & Initialisation

• constructor initialises interface with empty details

  public Address() { entry = new JPanel(new GridLayout(MAXDETAILS,2)); headings = new JLabel[MAXDETAILS]; details = new JTextField[MAXDETAILS];  for(int i=0;i<MAXDETAILS;i++) { headings[i]=setupLabel(text[i],entry); details[i]=setupTextField(“”,entry); } add(“Center”,entry);

Interface & Initialisation

controls = new JPanel(new GridLayout(MAXACTIONS,1)); actions = new JButton[MAXACTIONS]; for(int i=0;i<MAXACTIONS;i++) actions[i]= setupButton(actionText[i],controls); ... add(“West”,controls); }

Interface & Initialisation

• method to display Entry from array in interface

void showEntry(Entry e) { for(int i=0;i<MAXDETAILS;i++) details[i].setText(e.details[i]); }

• need to keep track of current Entry i.e. Entry on display in interface

int current; 

Interface & Initialisation

• at end of readEntries, need to set current Entry to first in array and display it

... file.close(); if(entryno!=0) { current=0; showEntry(entries[0]); } }

Interface & Initialisation

• write array back to file at end of program void doQuit() { if(entryno==0) System.exit(0); try { PrintWriter file = new PrintWriter(new FileWriter(addressbook)); for(int i=0;i<entryno;i++) entries[i].writeEntry(file); file.close(); System.exit(0); } catch(IOException e){}; }

Quit control

Add controls

• use a pair of JButtons• New – clear all details JTextFields– disable all JButtons apart from “Add”– user adds new details to empty JTextFields

• Add– copy details from JTextFields to new Entry– insert Entry into array in ascending name order– enable all JButtons and disable “Add”

Add controls

• disable Add in Address()at start actions[1].setEnabled(false);• for New– check if space in array

void doNew() { int i; if(entryno==MAXENTRIES) { System.out.println("More than "+ MAXENTRIES+" entries."); return; }

Add controls

– disable all JButtons and enable Add

actions[0].setEnabled(false); actions[1].setEnabled(true); for(i=2;i<MAXACTIONS;i++) actions[i].setEnabled(false);

– set all JTextFields to “”

for(i=0;i<MAXDETAILS;i++) details[i].setText(""); }

Add controls

• for Add…– get details from JTextFields and make new Entry

void doAdd() { int i,j; String [] newdetails = new String[MAXDETAILS]; for(i=0;i<MAXDETAILS;i++) newdetails[i]=details[i].getText(); Entry e = new Entry(newdetails);

Add controls

– search array to find first with name > new Entry’s name

for(i=0;i<entryno;i++) if(e.details[0].compareTo(entries[i].details[0])<0) break;

– move all Entrys down one place in array

for(j=entryno;j>i;j--) entries[j]=entries[j-1];

Add controls

– put new Entry in place, update count and remember new as current

entries[i]=e; current=i; entryno++;

– enable all JButtons and disable Add

actions[0].setEnabled(true); actions[1].setEnabled(false); for(i=2;i<MAXACTIONS;i++) actions[i].setEnabled(true); }

Move controls

• for Forward...– check if at end of array– increment current and display Entry

void doForward() { if(entryno==0 || current+1==entryno) return; current++; showEntry(entries[current]); }

Move controls

• for Back…– check if at start of array– decrement current and display Entry

void doBack() { if(entryno==0 || current==0) return; current--; showEntry(entries[current]); }

Delete control

• for Delete…– ignore if no Entrys

void doDelete() { if(entryno==0) return;

– move all Entrys after current back one place in array and decrement number of Entrys

for(int i=current;i<entryno-1;i++) entries[i]=entries[i+1]; entryno--;

Delete control

– if no Entrys then set all interface details to “” if(entryno==0) { for(int i=0;i<MAXDETAILS;i++) details[i].setText(""); return; }

– if deleted Entry was last Entry then reset current to new last Entry

if(current==entryno) current--;

Delete control

– display Entry in current position • usually Entry following deleted Entry

showEntry(entries[current]); }

Change control

• for Change…– user can alter any JTextField at any time– change only takes effect if Change selected– can’t just copy details back to current– if name changes then entry order changes– delete current entry– can’t use doDelete - updates text fields– add details from text fields as new entry - use doAdd

Change control void doChange() { if(entryno==0) return; for(int i=current;i<entryno-1;i++) entries[i]=entries[i+1]; entryno--; if(entryno==0) { for(int i=0;i<MAXDETAILS;i++) details[i].setText(""); return; } if(current==entryno) current--; doAdd(); }

Change control void doChange() { if(entryno==0) return; for(int i=current;i<entryno-1;i++) entries[i]=entries[i+1]; entryno--; if(entryno==0) { for(int i=0;i<MAXDETAILS;i++) details[i].setText(""); return; } if(current==entryno) current--; doAdd(); }

actionPerformed

int state;  final int INSPECT = 0; final int EXTEND = 1;  public void actionPerformed(ActionEvent e) { switch(state) { case INSPECT: if(e.getSource()==actions[0]) // NEW { doNew(); state = EXTEND; return; } if(e.getSource()==actions[2]) // CHANGE { doChange(); return; } if(e.getSource()==actions[3]) // DELETE { doDelete(); return; }

actionPerformed

if(e.getSource()==actions[4]) // UP { doForward(); return; } if(e.getSource()==actions[5]) // DOWN { doBack(); return; } if(e.getSource()==actions[6]) // QUIT { doQuit(); return; } case EXTEND: if(e.getSource()==actions[1]) // ADD { doAdd(); state = INSPECT; return; } } }}

main

class TestAddress{ public static void main(String [] args) throws IOException { Address a; a = new Address(); a.setSize(600,280); a.setTitle("Address"); a.setVisible(true); a.addWindowListener (new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); a.readEntries(); a.state = a.INSPECT; }}

Program

Improvements/extensions

1. add a JLabel to display system messages 2. after NEW, check that all requisite fields have

been filled in before ADD can succeed 3. add a search facility4. check for duplicate entries before CHANGE or

ADD can succeed