Understanding the Existing Code
There is already a decent amount of code included in the ImageShop project, across a few different files, so it is time well spent to ensure you understand what you are starting with.
GrayscaleImage.py
This program is introduced in the PDF reader on pg 287 (pdf page 293), and contains three function definitions to help with displaying a grayscale version of a particular image. Two of these functions will likely be useful to you in this project, but one will not. Take some time to review what each function is accomplishing, so that you understand which you will want to use later. Keep in mind that instead of copying these functions over to ImageShop.py
, you should instead import them. Again, you shouldn’t need to edit any code in this file, you’ll just import what you need and use it inside ImageShop.py
.
ImageShop.py
This is the main file that you will be editing through most of the milestones. It starts with code already present to draw the starting screen and add the first few buttons. This code and its major functionality is highlighted below, where you can click on the circled numbers to the right to bring up descriptions of each code block.
######################################################################
# Name:
# Collaborators (if any):
# Section leader's name:
# List of extensions made (if any):
######################################################################
"""
This program is the starter file for the ImageShop application, which
implements the "Load" and "Flip Vertical" buttons.
"""
from filechooser import choose_input_file
from pgl import GWindow, GImage, GRect
from button import GButton
# Constants
= 900
GWINDOW_WIDTH = 500
GWINDOW_HEIGHT = 125
BUTTON_WIDTH = 20
BUTTON_HEIGHT = 10
BUTTON_MARGIN = "#CCCCCC"
BUTTON_BACKGROUND
# Derived constants
= 2 * BUTTON_MARGIN + BUTTON_WIDTH
BUTTON_AREA_WIDTH = GWINDOW_WIDTH - BUTTON_AREA_WIDTH
IMAGE_AREA_WIDTH
# The image_shop application
def image_shop():
def add_button(label, action):
"""
Adds a button to the region on the left side of the window
label is the text that will be displayed on the button and
action is the callback function that will be run when the
button is clicked.
"""
= BUTTON_MARGIN
x = gw.next_button_y
y = GButton(label, action)
button
button.set_size(BUTTON_WIDTH, BUTTON_HEIGHT)
gw.add(button, x, y)+= BUTTON_HEIGHT + BUTTON_MARGIN
gw.next_button_y
def set_image(image):
"""
Sets image as the current image after removing the old one.
"""
if gw.current_image is not None:
gw.remove(gw.current_image)= image
gw.current_image = BUTTON_AREA_WIDTH + (IMAGE_AREA_WIDTH - image.get_width()) / 2
x = (gw.get_height() - image.get_height()) / 2
y
gw.add(image, x, y)
def load_button_action():
"""Callback function for the Load button"""
= choose_input_file()
filename if filename != "":
set_image(GImage(filename))
def flip_vertical_action():
"""Callback function for the Flip Vertical button"""
if gw.current_image is not None:
set_image(flip_vertical(gw.current_image))
= GWindow(GWINDOW_WIDTH, GWINDOW_HEIGHT)
gw = GRect(0, 0, BUTTON_AREA_WIDTH, GWINDOW_HEIGHT)
button_area True)
button_area.set_filled(
button_area.set_color(BUTTON_BACKGROUND)
gw.add(button_area)= BUTTON_MARGIN
gw.next_button_y = None
gw.current_image "Load", load_button_action)
add_button("Flip Vertical", flip_vertical_action)
add_button(
# Creates a new GImage from the original one by flipping it vertically.
def flip_vertical(image):
= image.get_pixel_array()
array return GImage(array[::-1])
# Startup code
if __name__ == "__main__":
image_shop()
- 0
- The initial imports of necessary functions. You will need to add to this later!
- 1
- The provided function to add a new button to the window. You need to provide both the text that should be displayed on the button and callback function to be run when the button is pressed. Note that the placement of the button is automatically determined. You should call this function whenever you want to create a new button.
- 2
-
The provided function to display a
GImage
to the screen. It takes care of clearing out the old value ofgw.current_image
, setting it to the new image, and then adding the image centered in the right portion of the window. You should call this function whenever you want to update what is displayed on the right side of the ImageShop window. - 3
-
The callback function responsible for prompting you for an image when the
Load
button is pressed. You should not need to edit this function, but you may want to draw inspiration from it when you need to implement a similar prompt as part of Milestone 3. - 4
-
The callback function which is run when the
Flip Vertical
button is pressed. Note how it accesses the current value ofgw.current_image
and passes it into theflip_vertical
function, then takes the output offlip_vertical
and sets the image on the screen to whatever imageflip_vertical
returned. This will be a very common pattern for many of the buttons you’ll create. - 5
- Initializes the major window components, a few variables, and then starts adding buttons. For the most part, you’ll just need to add your code to add your own buttons below this.
- 6
- The image manipulation function for flipping the image vertically. Note that it take in a GImage as an argument, and then returns a new GImage at the end. Again, this will be a pattern most of your image manipulation functions should follow.