Download presentation
Presentation is loading. Please wait.
Published byDamian Phelps Modified over 9 years ago
1
Computer Science 111 Fundamentals of Programming I Model/View/Controller and Data model design
2
I/O and Computations Add game logic to enforce rules and detect a winner Add arithmetic to perform calculations
3
The Model/View Pattern Data ModelView (User Interface) The data model consists of software components that manage a system’s data (game logic or calculations) The view consists of software components that allow human users to view and interact with the data model The view can be a TUI or a GUI, on the same data model
4
The View TicTacToeApp TTTSquare Button 9 EasyFrame EasyCanvas
5
The View and the Data Model TicTacToe list String 9 TicTacToeApp TTTSquare Button 9 displays EasyFrame EasyCanvas
6
Model/View/Controller Pattern GUI-based, event-driven programs can be further decomposed by gathering code to handle user interactions into a third component called the controller Controller ModelView Manages data Displays data Responds to user events
7
The Controller In Python, the controller consists of the methods that respond to user events These methods are defined in the main view class, and are associated with the command attribute of the buttons Other types of widgets can have their own event- handling methods (for mouse presses, etc.)
8
Event-Driven Programming Set up a window with its widgets Connect it to a data model Wait for users to press buttons, enter text, drag the mouse, etc. Respond to these events by running methods that update the data model and the view
9
Add a Data Model to Tictactoe A rough prototype of the model tracks just the current letter (X or O) The model’s initial state contains a randomly chosen letter The method nextLetter() changes the model’s state to the other letter and returns that letter
10
model = TicTacToe() # Returns a new model with a randomly chosen letter str(model) # Returns the string rep of the model letter = model.nextLetter() # Changes state to the other letter and returns it model.newGame() # Resets the state to a randomly chosen letter The Model’s Interface These are the operations that the view and the controller know about and can use
11
class TicTacToeApp(EasyFrame): """Displays a tictactoe board in the window.""" def __init__(self): """Sets up the window and the panels.""" EasyFrame.__init__(self, title = "TicTacToe") self.model = TicTacToe() # Create the model color = "black" number = 0 for row in range(3): for column in range(3): square = TTTSquare(parent = self, width = 50, height = 50, background = color, number = number, model = self.model) # Pass it to each square self.addCanvas(square, row = row, column = column) number += 1 if color == "black": color = "white" else: color = "black" Changes to Main View Class When the user clicks in a square, that square gets a letter from the model to display in the view
12
class TTTSquare(EasyCanvas): """Represents a tictactoe square.""" def __init__(self, parent, width, height, background, number, model): """Sets up the tictactoe square.""" EasyCanvas.__init__(self, parent, width = width, height = height, background = background) self.model = model # Save a reference to the model self.number = number self.width = width self.height = height self.letter = "" # No letter in the square yet def mousePressed(self, event): """Displays an X or an O if the square is unoccupied.""" if not self.letter: self.letter = self.model.nextLetter() # Access the model self.drawText(self.letter, self.width // 2, self.height // 2, fill = "red") Changes to the Canvas Class When the user clicks in a square, that square gets a letter from the model to display in the view
13
import random class TicTacToe(object): """Models a tictactoe game.""" def __init__(self): """Sets up the model.""" self.newGame() def __str__(self): """Returns the string rep of the model.""" return self.letter def newGame(self): """Resets the game to its initial state.""" self.letter = random.choice(("X", "O")) def nextLetter(self): """Returns the next letter for play.""" if self.letter == "X": self.letter = "O" else: self.letter = "X" return self.letter The Model Class
14
def main(): """Starting point for the application.""" model = TicTacToe() print(model) for count in range(5): print(model.nextLetter()) if __name__ == "__main__": main() Testing the Model Since the model is independent of any view, you can (and should) test it thoroughly before hooking a view onto it
15
Add a Data Model to the Calculator Calculator total CalculatorApp Button Label 19 displays EasyFrame
16
Add a Data Model to the Calculator The model will handle the calculation when the +, -, X, /, or = button is clicked The model tracks a running total, as well as a previous operator and operand The controller –Obtains the number in the digits label –Passes the operator and the number to the model –Resets the digits label to the result
17
model = Calculator() # Returns a new model with total = 0 str(model) # Returns the model’s state (the current total) model.applyOperator(operator, # Performs an arithmetic operation and updates the operand) # total The Model’s Interface When the operator is =, applyOperator works with a previous operator and possibly a previous operand, if they exist; the model tracks these as well
18
class CalculatorApp(EasyFrame): """Displays labels in the window's quadrants.""" def __init__(self): """Sets up the window and the labels.""" EasyFrame.__init__(self, background = "black", title = "Calculator", resizable = False) self.calculator = Calculator() # Instantiate the data model self.operatorEntered = False self.digitsLabel = self.addLabel("0", row = 0, column = 0, columnspan = 4, sticky = "E") self.addButton("/", row = 1, column = 3, command = self.makeOperatorCommand("/")) # buttons for 3 other operators, X, +, -, go here self.addButton("0", row = 5, column = 0, command = self.makeDigitCommand("0")) # Buttons for other digits and operators go here Changes to Main View Class makeOperatorCommand builds a command for each operator
19
class CalculatorApp(EasyFrame): """Displays labels in the window's quadrants."””. def clear(self): """Restores the model and view to their original states.""" self.calculator = Calculator() self.operatorEntered = False self.digitsLabel["text"] = "0" self.clearButton["text"] = "AC" Changes to Main View Class clear creates a new model, resets the view’s reference to it, and updates the view
20
class CalculatorApp(EasyFrame): """Displays labels in the window's quadrants."””. # Event handling method builder for digit buttons def makeDigitCommand(self, buttonText): """Define and return the event handler for a button.""" def addDigit(): if self.operatorEntered or self.digitsLabel["text"] == "0": self.digitsLabel["text"] = "" self.operatorEntered = False self.digitsLabel["text"] += buttonText if buttonText != "0": self.clearButton["text"] = "C" return addDigit The Controller for All Digits operatorEntered is True after an operator is entered, which allows the user to begin a new series of digits When it’s False, the user continues the series of digits
21
class CalculatorApp(EasyFrame): """Displays labels in the window's quadrants."””. # Event handling method builder for /, X, +, -, and = buttons def makeOperatorCommand(self, buttonText): """Define and return the event handler for a button.""" def applyOperator(): number = self.digitsLabel["text"] if "." in number: number = float(number) else: number = int(number) self.calculator.applyOperator(buttonText, number) self.digitsLabel["text"] = str(self.calculator) self.operatorEntered = True return applyOperator The Controller for 4 Operators Get the label’s text, convert it to the appropriate number, pass it and the operator to the model for calculation, and display the model’s state
22
For Friday Read Chapter 2 on Collections
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.