27
Computer Science 112 Fundamentals of Programming II Graphics Programming

Computer Science 112 Fundamentals of Programming II Graphics Programming

Embed Size (px)

Citation preview

Computer Science 112

Fundamentals of Programming IIGraphics Programming

Bitmapped Display

• Think of the monitor screen as a rectangular grid that is divided up into tiny square pieces

• Each square piece is called a picture element or pixel

• Each pixel can be painted – black or white (monochrome)– Several shades of gray (grayscale)– Several (perhaps millions of) colors

• The values of the colors are represented as bits in a structure called a bitmap

Representing Colors: Monochrome

• Black and white: 0 = black, 1 = white, so just a single bit

• 8, 16, 128, or 256 shades of gray: 3, 4, 7, or 8 bits (why?)

• In general, N bits allows 2N distinct color values

Representing Colors: RGB

• The RGB system composes each color from red, green, and blue components

• Each component is an integer in the range 0..255

• 0 means the total absence of a color component

• 255 means the highest saturation of a color component

• 256 * 256 * 256 = 16,777,216 distinct color values

Representing Colors: RGBThink of each color value as a triple of integers of the form (<r>, <g>, <b>)

RGB Triple Color

(0, 0, 0) Black

(255, 0, 0) Red

(0, 255, 0) Green

(0, 0, 255) Blue

(127, 127, 127) Medium Gray

(255, 255, 255) White

Python Color Values

• Some common colors are “black”, “red”, etc.

• Or a string of the form “xRRGGBB”, where RR is the red value in hexadecimal, etc.

• Example: “xffffff” is white, “xff0000” is red, etc.

Screen Coordinates

• The origin (0, 0) is in the upper left corner of the screen, and y values increase towards the bottom border

• Each pixel has an (x, y) position in the grid

The Canvas Widget

• A canvas is a rectangular area in which one can draw images or shapes, and detect mouse events

• The method addCanvas– creates a new object of type EasyCanvas– adds it to the window’s grid at the given row and column

– returns the canvas

– optional arguments include background, width, and height

class CanvasDemo(EasyFrame): """Draws filled ovals on a canvas."""

def __init__(self): """Sets up the window and widgets.""" EasyFrame.__init__(self, title = "Canvas Demo")

self.canvas = self.addCanvas(row = 0, column = 0, width = 300, height = 150, background = "black") self.ovalButton = self.addButton(text = "Draw oval", row = 1, column = 0, command = self.drawOval)

class CanvasDemo(EasyFrame): """Draws filled ovals on a canvas."""

. . .

def drawOval(self): """Draws a filled oval at a random position.""" x = random.randint(0, 300) y = random.randint(0, 150) self.canvas.drawOval(x, y, x + 25, y + 25, fill = "red")

Drawing Shapes on a Canvas

Each method returns a number that identifies the shape object in the canvas

Other Manipulations of Shapes

Each method uses the number identifying a given shape on the canvas

class CanvasDemo(EasyFrame): """Draws filled ovals on a canvas."""

def __init__(self): """Sets up the window and widgets.""" EasyFrame.__init__(self, title = "Canvas Demo")

self.canvas = self.addCanvas(row = 0, column = 0, columnspan = 2, width = 300, height = 150, background = "black") self.clearButton = self.addButton(text = "Clear", row = 1, column = 1, command = self.clear)

class CanvasDemo(EasyFrame): """Draws filled ovals on a canvas."""

def __init__(self): """Sets up the window and widgets.""" EasyFrame.__init__(self, title = "Canvas Demo") # Must now track all ovals drawn self.ovals = list()

self.canvas = self.addCanvas(row = 0, column = 0, columnspan = 2, width = 300, height = 150, background = "black") self.clearButton = self.addButton(text = "Clear", row = 1, column = 1, command = self.clear)

class CanvasDemo(EasyFrame): """Draws filled ovals on a canvas."""

def drawOval(self): """Draws a filled oval at a random position.""" x = random.randint(0, 300) y = random.randint(0, 150) oval = self.canvas.drawOval(x, y, x + 25, y + 25, fill = "red") self.ovals.append(oval)

def clear(self): """Erases the ovals from the canvas.""" for oval in self.ovals: self.canvas.delete(oval) self.ovals = list()

Choosing a New Color

The function tkinter.colorchooser.askcolor() pops up a color chooser

Returns a tuple of two elements, which are both None if Cancel was chosen

The second element is the chosen color, otherwise

import tkinter.colorchooser

class CanvasDemo(EasyFrame): """Draws filled ovals on a canvas.""" def __init__(self): """Sets up the window and widgets.""" EasyFrame.__init__(self, title = "Canvas Demo") self.ovals = list() self.color = "red"

self.colorButton = self.addButton(text = "Color", row = 1, column = 2, command = self.chooseColor) . . .

def drawOval(self): """Draws a filled oval at a random position.""" x = random.randint(0, 300) y = random.randint(0, 150) oval = self.canvas.drawOval(x, y, x + 25, y + 25, fill = self.color) self.ovals.append(oval)

def chooseColor(self): """Allows the user to change the color.""" colorTuple = tkinter.colorchooser.askcolor() if colorTuple[0]: self.color = colorTuple[1]

Defining a Special-Purpose Canvas

• You define a new canvas class, as a subclass of EasyCanvas, when– there is a lot going on in the canvas

– you want to detect and respond to mouse events in the canvas

• The method addCanvas allows an optional canvas argument

• You create an instance of the special-purpose canvas first, then add it to the window with addCanvas

Mouse Events and Methods

When a mouse event occurs in a canvas, Python runs one of these methods (which does nothing by default)

You override the definition to do something

The event parameter contains x and y fields that represent the current mouse coordinates in the canvas

from breezypythongui import EasyFrame, EasyCanvas

class MouseDemo(EasyFrame): """Draws coordinates of mouse presses on a canvas."""

def __init__(self): """Sets up the window and widgets.""" EasyFrame.__init__(self, title = "Mouse Demo")

shapeCanvas = ShapeCanvas(parent = self) self.addCanvas(canvas = shapeCanvas, row = 0, column = 0, width = 300, height = 150)

A canvas subclass needs to know about its parent window

from breezypythongui import EasyFrame, EasyCanvas

. . .

class ShapeCanvas(EasyCanvas): """Displays the coordinates of the point where the mouse is pressed."""

def __init__(self, parent): """Background is gray.""" EasyCanvas.__init__(self, parent, background = "gray")

def mousePressed(self, event): """Draws the coordinates of the mouse press.""" coordString = "(" + str(event.x) + "," + str(event.y) + ")" self.drawText(coordString, event.x, event.y)

A canvas subclass needs to know about its parent window

Tictactoe

Prototype: Display Positions

Classes:

TicTacToeApp (main window)

TTTSquare (9 canvases)

Behavior:

Displays a square position in response to a mouse press

from breezypythongui import EasyFramefrom tttsquare1 import TTTSquare

class TicTacToeApp(EasyFrame): """Displays a tictactoe board in the window."""

def __init__(self): """Sets up the window and the squares.""" EasyFrame.__init__(self, title = "TicTacToe") 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) self.addCanvas(square, row = row, column = column) number += 1 if color == "black": # Alternate square colors color = "white" else: color = "black")

The Main Window Class

from breezypythongui import EasyCanvas

class TTTSquare(EasyCanvas): """Represents a tictactoe square."""

def __init__(self, parent, width, height, background, number): """Sets up the tictactoe square.""" EasyCanvas.__init__(self, parent, width = width, height = height, background = background) self.number = number self.width = width self.height = height def mousePressed(self, event): """Draws the square's number in its center.""" self.drawText(str(self.number), self.width // 2, self.height // 2, fill = "red")

The Canvas Class

Completing the GUI Apps

• The GUI is responsible for showing the state of the data and providing controls for the user to manipulate

• The data model is responsible for representing and processing the application’s data (the logic of a calculator or a tictactoe game)

For Wednesday

The Model/View/Controller Pattern

Designing a Data Model