tk.Misc.lift(canvas) seemingly not working - python

The full code for the chess game im making
import chess
#from stockfish import Stockfish
import tkinter as tk
import time
board = chess.Board()
def boardtoarr(board): #converts chess board string to 2d array
boardlist = []
linelist = []
for b in range(0,128,2):
linelist.append(str(board)[b])
if len(linelist) == 8:
boardlist.append(linelist)
linelist = []
return boardlist
#given the square of a piece on the board, returns the legal squares the piece can move to
def piecelegalmoves(square,cboard):
ans = []
for a in cboard.legal_moves:
a = str(a)
if a[0:2] == square:
ans.append(a[2::])
return ans
def alllegalmoves(cboard): #given a chess board it will return all legal moves
x = str(cboard.legal_moves)[38:-2]
x = x.split(', ')
return x
squarevar = [] #variable to contain the starting square and the moving-to square
def squareclicked(event):
global squarevar
x,y = event.x,event.y
#print(x,y)
#print(pixeltosquare(x,y))
#print(lsquaretocsquare(pixeltosquare(x,y)))
#squarevar.append(lsquaretocsquare(pixeltosquare(x,y)))
#print(squarevar)
return lsquaretocsquare(pixeltosquare(x,y))
def highlightlegalmoves(piece,board):
global BoardImage,redsquare
#for widget in root.winfo_children(): #code to clear page
#widget.destroy()
legalmoves = piecelegalmoves(piece,board)
canvas = tk.Canvas(root,width = BoardImage.width(), height = BoardImage.height())
#canvas = tk.Canvas(root,width = 500, height = 500)
canvas.pack()
for a in legalmoves:
x = csquaretolsquare(a)
print(x)
pixel = topleftpixels(x[0],x[1])
#canvas.create_image(0,0, image = redsquare, anchor = 'nw')
canvas.create_image(pixel[1],pixel[0], image = redsquare, anchor = 'nw')
tk.Misc.lift(canvas)
def makemoves(event): #Function to make chess moves when clicks have been inputted
global squarevar
squarevar.append(squareclicked(event))
if len(squarevar) != 2:
#print(squarevar[0])
highlightlegalmoves(squarevar[0],board)
if len(squarevar) == 2:
if squarevar[1] in piecelegalmoves(squarevar[0],board): #checking if move is legal to prevent errors (input validation)
board.push_san(squarevar[0]+squarevar[1]) #play move on backend board
squarevar = []
for widget in root.winfo_children(): #code to clear page
widget.destroy()
boardtoimage(root,str(board))
else:
squarevar = []
def topleftpixels(x,y): #returns top left pixel of given square
return [x*100,y*100]
def pixeltosquare(x,y): #given a pixel it will return what chess square it is on
x = ('000' + str(x))
x = x[len(x)-3::]
y = ('000' + str(y))
y = y[len(y)-3::]
return [int(y[0]),int(x[0])]
def csquaretolsquare(square): #converts chess square notation to list square notation
ans = []
letterorder = 'abcdefgh'
ans.append(8-int(square[1]))
ans.append(letterorder.index(square[0]))
return ans
def lsquaretocsquare(square): #converts list square notation to chess square notation
ans = ''
letterorder = 'abcdefgh'
ans += (letterorder[square[1]])
ans += str(8-square[0])
return ans
def boardtoimage(root,boardstr): #places all pieces onto the window graphically
global wQueen,wKing,wKnight,wBishop,wPawn,wRook,bQueen,bKing,bKnight,bBishop,bPawn,bRook,BoardImage
LetterToImage= {
'r': bRook, 'n': bKnight, 'b': bBishop, 'q': bQueen, 'k': bKing, 'p': bPawn,
'R': wRook, 'N': wKnight, 'B': wBishop, 'Q': wQueen, 'K': wKing, 'P': wPawn,
}
boardcanvas = tk.Canvas(root,width = BoardImage.width(), height = BoardImage.height()) #This will be the canvas for the whole board, pieces and all
boardcanvas.pack()
boardcanvas.create_image(0,0, image = BoardImage, anchor = 'nw') #placing chess board on canvas
#iterate through board and place piece images in correct place
for y in range(8):
for x in range(8):
piece = boardtoarr(boardstr)[y][x]
if piece in LetterToImage.keys():
boardcanvas.create_image(topleftpixels(x,y)[0], topleftpixels(x,y)[1], image=LetterToImage[piece], anchor="nw")
boolvar = False
def CMI_clicked(): #check if the chess menu image was clicked
global root
global BoardImage
global boolvar
for widget in root.winfo_children(): #code to clear page
widget.destroy()
boardtoimage(root,str(board))
root.bind("<Button-1>", makemoves)
def Menu():
global root
global ChessMenuImage
#Menu
ChessMenuOption = tk.Button(root ,image = ChessMenuImage, command = CMI_clicked) #create button using chess menu image and call function 'CMI_clicked' when pressed
ChessMenuOption.place(x = 380, y = 380) #place the chess menu image at given coordinates
root = tk.Tk()
ChessMenuImage = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\Chess_Selection_Image.png') #Load chess menu image file
BoardImage = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\ChessBoardImage.png') #Load board image file
redsquare = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\redsquare.png') #Load see-through red square file, used for showing legal moves in the GUI
#Piece image loading
#White
wQueen = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wQueen.png')
wKing = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wKing.png')
wPawn = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wPawn.png')
wBishop = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wBishop.png')
wKnight = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wKnight.png')
wRook = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wRook.png')
#Black
bQueen = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bQueen.png')
bKing = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bKing.png')
bPawn = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bPawn.png')
bBishop = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bBishop.png')
bKnight = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bKnight.png')
bRook = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bRook.png')
root.geometry('800x800')
Menu()
root.mainloop()
specifically lines 47-61 'highlightlegalmoves' function
def highlightlegalmoves(piece,board):
global BoardImage,redsquare
#for widget in root.winfo_children(): #code to clear page
#widget.destroy()
legalmoves = piecelegalmoves(piece,board)
canvas = tk.Canvas(root,width = BoardImage.width(), height = BoardImage.height())
#canvas = tk.Canvas(root,width = 500, height = 500)
canvas.pack()
for a in legalmoves:
x = csquaretolsquare(a)
print(x)
pixel = topleftpixels(x[0],x[1])
#canvas.create_image(0,0, image = redsquare, anchor = 'nw')
canvas.create_image(pixel[1],pixel[0], image = redsquare, anchor = 'nw')
tk.Misc.lift(canvas)
so if I run the code
for widget in root.winfo_children(): #code to clear page
widget.destroy()
the image I get (before/after I click a piece)
before:
after (I clicked the e2 pawn):
so I know that under the original canvas its actually displaying what I want. I just what to show to lift it but its not doing that.
when I have the delete all widgets code commented, the image does not change once I click a piece, it does not display the legal moves of the piece.

Related

Why does my program require me to press the enter key before continuing (python tkinter)

I am making a program, using python tkinter, which simply prints some circles to the screen (I call it a board in this program). The program moves on to a different "board" once the mouse cursor moves over the button. The problem I have is that I simply call the "create_board" function 3 times using a for loop however in-between each iteration of the loop the "enter" key must be pressed. This isn't a massive deal but I'm trying to understand why and if there is a way to remove this requirement and have the next board load automatically.
I'm certain it has something to do with the tkinter windows and triggering the command "destroy" once the buttons (circles) are pressed however I'm still learning how to effectively use tkinter and any help would be very much appreciated.
def create_board(user_name, board):
# define the name of tkinter window
win = Tk()
# get the size of the displace for position and size calculations
app = wx.App(False)
w, h = wx.GetDisplaySize()
name = user_name
# define variables based on board number
if board == 0:
gx_pos = int(w/8) # locations of circles
gy_pos = int(h/8)
bx_pos = (w/8)*5
by_pos = (h/8)*5
board_num = str(1)
elif board == 1:
gx_pos = int(w/12)
gy_pos = int(h/12)
bx_pos = (w/6)*5
by_pos = (h/6)*5
board_num = str(2)
elif board == 2:
gx_pos = int(w/3)
gy_pos = int(h/3)
bx_pos = (w/3)*2
by_pos = (h/3)*2
board_num = str(3)
# records the mouse cursor position into a file along with time taken
def record_pos(x, y, board_num, s):
filename = name + "_" + board_num + ".txt"
try:
os.path.isfile('./'+filename)
except:
open(filename, 'r')
with open(filename, 'a') as f:
f.write(str(x) + "," + str(y) + "," + str(s) + "\n")
# determining when left click should be made
def mouse_pos():
flags, hcursor, (x, y) = win32gui.GetCursorInfo()
time_taken = time.time()
record_pos(x, y, board_num, time_taken)
mouse.click('left')
win.after(500, mouse_pos)
# wait 3 seconds before loading first board
time.sleep(3)
geometry = "%dx%d" % (w,h)
win.geometry(geometry)
win.attributes('-fullscreen', True)
win.config(cursor="circle")
# get the grid image
bg = Image.open("grid_image.png")
img = bg.resize((w, h))
grid_img=ImageTk.PhotoImage(img)
image_label = Label(win, image=grid_img)
image_label.place(x=0, y=0, relwidth=1, relheight=1)
# print an image of a green circle
gw = int(w/26)
gh = int(h/15)
g_circle = Image.open('green_circle.png')
g_img = g_circle.resize((gw,gh))
g_circle_image=ImageTk.PhotoImage(g_img)
g_label = Label(win, image=g_circle_image)
g_label.place(x = gx_pos,y = gy_pos)
g_btn = Button(win, image=g_circle_image, command = win.destroy)
g_btn.place(x= gx_pos , y= gy_pos)
# print an image of a blue circle
bw = int(w/26)
bh = int(h/15)
b_circle = Image.open('circle.png')
b_img = b_circle.resize((bw,bh))
b_circle_image=ImageTk.PhotoImage(b_img)
b_label = Label(win, image=b_circle_image)
b_label.place(x=bx_pos, y=by_pos)
b_btn = Button(win, image=b_circle_image, command = win.destroy)
b_btn.place(x=bx_pos, y=by_pos)
# record mouse position
mouse_pos()
win.mainloop()
EDIT: I added the simple for loop that I'm using to iterate through the boards.
for i in range(3):
create_board(user_name, i)
The issue was caused by using time.sleep() in tkinter. After removing this the code runs with out requiring an enter key press each time.

Canvas shows only one picture(the last) from the list

I'm trying to draw a chessboard by canvas, but I get only one piece at the end of the code. I tried to draw a line and it still exists, but piece no!
Here is the code:
from tkinter import *
class pawn:
def __init__(self,coords, color, board):
self.color = color
self.board = board
self.type = "pawn"
self.x = coords[0]
self.y = coords[1]
pass
def draw_board(board):
root = Tk()
canvas = Canvas(root, width=512, height=512)
canvas.pack()
for line in range(8):
for cell in range(8):
if board[line][cell] != "":
l = r"C:\python\Chess\images\ "[:-1]
l = l + board[line][cell].type + board[line][cell].color[0] + ".png"
print(l)
img = PhotoImage(file=l)
canvas.create_image(32 + line*64, 32 + cell*64, image=img)
root.mainloop()
board = [[""for j in range(8)] for k in range(8)]
pawn_1 = pawn([1,1],"White",board)
pawn_2 = pawn([2,2],"Black",board)
board[2][2] = pawn_1
board[1][1] = pawn_2
draw_board(board)
It's working with one piece, but if I create 2 in the list, it'll draw only the last.

Python (pygame/tkinter) MP3 Playlist

# -*- coding: utf-8 -*-
"""
"""
from tkinter import *
import pygame
from tkinter.messagebox import *
from tkinter import filedialog
#-------------------------------FONCTIONS---------------------------------
def importer_son(event):
file = filedialog.askopenfilename()
pygame.init()
pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.mixer.init()
Liste_musique.append(file)
#TEST PRINT
print(file)
print (Liste_musique)
def stop_it(event):
pygame.mixer.music.pause()
global pause
pause = 1
def start_it(event):
global pause
if pause == 1:
pygame.mixer.music.unpause()
pause = 0
else:
try:
pygame.mixer.music.load(Liste_musique[index])
pygame.mixer.music.play()
except:
showwarning("Error","PAS DE FICHIER")
def close():
pygame.mixer.music.stop()
fen1.destroy()
def next_musique(event):
global index
index += 1
try:
pygame.mixer.music.load(Liste_musique[index])
pygame.mixer.music.play()
except:
showwarning("Error","PAS DE FICHIER")
def previous_musique(event):
global index
index -= 1
try:
pygame.mixer.music.load(Liste_musique[index])
pygame.mixer.music.play()
except:
showwarning("Error","PAS DE FICHIER")
def reint():
pygame.mixer.music.stop()
Liste_musique[:] = []
#-------------------------------Variables---------------------------------
Liste_musique = []
global index
index = 0
global pause
pause = 0
#-------------------------------MAIN---------------------------------
fen1 = Tk()
fen1.title("Lecteur Audio en python")
menubar = Menu(fen1)
menu1 = Menu(menubar, tearoff=0)
menu1.add_command(label="RĂ©initialiser", command=reint)
menu1.add_command(label="Quitter", command=close)
menubar.add_cascade(label="Option", menu=menu1)
fen1.config(menu=menubar)
can1 = Canvas(fen1, height=500, width=500)
can1.pack(side=LEFT, padx=5, pady=5)
fond_decran = PhotoImage(file="Background.gif")
can1.create_image(0,0, anchor = "nw", image = fond_decran)
can1.image = fond_decran
image_play = PhotoImage(file="Play.gif")
im_play = can1.create_image(50,400, anchor = "nw", image = image_play)
can1.image = image_play
image_stop = PhotoImage(file="stop.gif")
im_stop = can1.create_image(130,400, anchor = "nw", image = image_stop)
can1.image = image_stop
image_prev = PhotoImage(file="prev.gif")
im_prev = can1.create_image(210,400, anchor = "nw", image = image_prev)
can1.image = image_prev
image_next = PhotoImage(file="next.gif")
im_next = can1.create_image(290,400, anchor = "nw", image = image_next)
can1.image = image_next
image_importer = PhotoImage(file="importer.gif")
im_importer = can1.create_image(370,400, anchor = "nw", image = image_importer)
can1.image = image_importer
can1.tag_bind(im_play, '<Button-1>', start_it)
can1.tag_bind(im_stop, '<Button-1>', stop_it)
can1.tag_bind(im_next, '<Button-1>', next_musique)
can1.tag_bind(im_prev, '<Button-1>', previous_musique)
can1.tag_bind(im_importer, '<Button-1>', importer_son)
fen1.mainloop()
fen1.destroy()
In the code above I created my mp3 player, it works well but I would like to do a "playlist" : when a music is end go to the next or if there is only one music that it repeats it. To do that I already have a list with all songs (Liste_musique) and an index (index) to see where I am in the list. But I don't see how can I do that. I hope I could have explained well: D
Thanks for your help
Nae : See pygame.mixer.music.get_busy(), pygame.mixer.music.queue,
pygame.mixer.music.set_endevent, pygame.mixer.music.get_endevent()
Good answer

Generator for placing images on tkinter canvas

I have a list of paths to around 90 images, now I want to place all of them on the canva,but only let's say 30 in one "row", but if I use
from tkinter import *
def createCanvaImages(paths):
paths = ['list with the paths']
mainWin = Tk()
canva = Canvas(mainWin, width = 900, height = 300).pack()
for x in range(0, len(paths),):
if x <= 30: #not sure if this places only 30 in one row
y=x/3
elif x > 30
y=(x+24)/3
elif x >= 60
y=(x+48)/3
img = PhotoImage(file = paths[x])
canva.create_image(x+24, y, image = img)
mainWin.mainloop()
it only shows the image from the last path
EDIT
now shows all images on the canvas if the canvas isn't in a frame(thanks to Novel) but doesn't work if the canva is in a frame
from tkinter import *
def createImagePaths(dct):
paths=[]
for i in range(len(masteries)):
if dct.get(masteries[i]) == 0:
file = masteries[i]+'.png'
path = os.path.join(path_gray, file)
paths.append(path)
#create canvas image fnc
if dct.get(masteries[i]) != 0:
file = masteries[i]+'.png'
path = os.path.join(path_colored, file)
paths.append(path)
return createCanvaImages(paths)
def createCanvaImages(paths):
img_refs = []
canva = Canvas(masteryFrame, height = 400).pack()
for i, path in enumerate(paths):
col,row = divmod(i,30)
img = PhotoImage(file=path)
canva.create_image( row*24, col*24, image = img, anchor = 'nw')
img_refs.append(img)
root = Tk()
mainFrame = Frame(root)
mainFrame.grid(column=0,row=0, sticky=(N,W,E,S))
masteryFrame = Frame(root)
masteryFrame.grid(row=1,column=0, sticky=(N,W,E,S))
root.mainloop()
You need to save your image references. The easiest way to do that is to just add them to a list. As a guess:
from tkinter import *
def createCanvaImages(paths):
canva = Canvas(masteryFrame, width = 900, height = 300)
canva.pack()
canva.img_refs = []
for i, path in enumerate(paths):
row, col = divmod(i, 30)
img = PhotoImage(file = path)
canva.create_image(col*24, row*24, image = img, anchor='nw') # each image is 24x24
canva.img_refs.append(img)
Also, make sure you never put a widget initialization and layout on the same line. IOW, don't ever do this: Widget(master).pack(). Always put those on separate lines.
You should also learn about OOP and classes very soon. Using functions to build the UI like this will get very messy and buggy very quickly.

Tkinter: Can't add more than 3 PhotoImages to a list for animation?

I'm trying to program a game in Tkinter (trust that I'd much rather use another better-suited library), and I'm having trouble coding in animations. I tried 2 ways of working around the problem but both have failed.
What I've done is to write an Animation class, which, in my first implementation, takes a list of PhotoImages, and deletes/draws each frame:
class Animation():
def __init__(self, container, pos, images, framerate):
self.container = container
self.x = pos[0]
self.y = pos[1]
self.images = copy(images)
self.imagescopy = copy(images)
self.framerate = framerate # ms between frames
self.done = False
def animate(self):
if len(self.images)>0:
self.container.delete("currentframe")
self.container.create_image(self.x, self.y, image = self.images.pop(0), tag = "currentframe")
self.animation = self.container.after(self.framerate, self.animate)
else:
self.container.delete("currentframe")
self.container.after_cancel(self.animation)
self.done = True
In the init method of the class which draws the Tk window, I loaded the PhotoImages (I tried this with a simple placeholder 5 frame animation):
for i in range(1,6):
self.imgs_playbgready.append(PhotoImage(file ='Graphics\\PlayArea\\ani_bgready'+str(i)+'.gif'))
But when I try to execute the program, it takes very very long to load beyond the third image. Even writing out each line explicitly like so:
self.imgs_playbgready = [PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready1.gif'),
PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready2.gif'),
PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready3.gif'),
PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready4.gif'),
PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready5.gif') ]
didn't help. Removing the last 2 items seems to make everything fine, so it looks like there's a limit on 3 PhotoImages in a list though I can't imagine why that'd be the case?
In my second implementation, I tried to change the animate method so that the PhotoImages would be 'lazily loaded' (so now self.images is a list of file names rather than PhotoImages):
def animate(self):
if len(self.images)>0:
self.container.delete("currentframe")
image = PhotoImage(file = self.images.pop(0))
self.container.create_image(self.x, self.y, image = image, tag = "currentframe")
self.animation = self.container.after(self.framerate, self.animate)
else:
self.container.delete("currentframe")
self.container.after_cancel(self.animation)
self.done = True
Now when I try to run the program it freezes at frame 4 and I have to force quit. Again, it seems 3 is the magic number?
I'm not really sure at all what's going on with this. From googling about animation in Tkinter, redrawing PhotoImages frame by frame seems the way to go. Please be patient with me because I only started learning to use the Tkinter library last week. Any help is much appreciated.
EDIT
Thanks for your help.
To clarify the points raised in the comment (full working code at the end):
It takes a few minutes before the last two images load in and the program starts up. My framerate as defined in the Animation class is more like an inverse framerate (number of miliseconds between each redraw) as you can see in the animate function. My whole code is really quite long so I will try to extract the more relevant parts (for the first implementation I tried). Basically in my GUI class (named PlayArea), under the __init__ method, I try to load in the image list for the animation as well as create an Animation instance:
class PlayArea():
def __init__(self):
self.window = Tk()
.....
#---------------------
# Button and background images
#---------------------
......
self.imgs_playbgready = [PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready1.gif'),
PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready2.gif'),
PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready3.gif'),
PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready4.gif'),
PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready5.gif') ]
.......
self.ani_playbgready = Animation(self.playCanvas,(self.playWidth/2, self.playHeight/2),self.imgs_playbgready, 5000)
The animation will only run after a user clicks a button, and the command callback for the button is this(I've put in only the relevant portions):
startGame(self):
# Play Area
self.playCanvas.delete("bgready")
self.ani_playbgready.animate() # animating the images
I know for sure that the program is freezing up after loading the third PhotoImage, because when I try to do the loading using a for loop, and print the list after each loop, I can see it hang up in the fourth one. As mentioned, this code works as long as I only load 3 images into the list. In other words, it probably isn't a problem with my animate method
The monstrous block of working code as requested:
from Tkinter import *
import tkFont
from PIL import Image, ImageTk
from copy import deepcopy, copy
#------------------------------------------------
# Player, Controller, Levels, and Customer
#------------------------------------------------
class Player():
'''
Player class to keep track of progress of specific player.
Progress and highscore will be written to a save file
'''
def __init__(self, name = "Default", highscore = 0, currentlevel = 1):
self.name = name
self.highscore = highscore
self.currentlevel = currentlevel
class Controller():
'''
Controller which keeps track of score as well as the timer.
To be instantiated by the GUI class to determine the score and time left to display
'''
def __init__(self):
self.score = 0
self.level = 1
self.timer = 10
def runTimer(self):
if self.timer > 0:
self.timer -= 1
else:
self.timer = 10
class Levels():
'''
Contains the commands(tasks) for each level, as well as the order of customers and the
corresponding answers.
To be instantiated by the GUI class to determine the current command and customer to display
'''
def __init__(self):
#--------------------------------------------------------------
# Initialize commands, anwers and customers for each level (hardcode for now, may be a way to
# randomize or dynamically generate challenges depending on the level design)
# Customers can have more than one attribute, so we store it as a tuple
# Answers for each customer can be more than one pizza (eg. for a while loop), so store it as a tuple
# If the statement doesn't execute, correct answer is to move on to the next customer
#---------------------------------------------------------------
# Level 1
# Action images
self.img_pepperoni = (PhotoImage(file = 'Graphics\\Actions\\pepperoniup.gif'),
PhotoImage(file = 'Graphics\\Actions\\pepperonihover.gif'),
PhotoImage(file = 'Graphics\\Actions\\pepperonidown.gif'))
self.img_hawaiian = (PhotoImage(file = 'Graphics\\Actions\\hawaiianup.gif'),
PhotoImage(file = 'Graphics\\Actions\\hawaiianhover.gif'),
PhotoImage(file = 'Graphics\\Actions\\hawaiiandown.gif'))
self.img_vegetarian = (PhotoImage(file = 'Graphics\\Actions\\vegetarianup.gif'),
PhotoImage(file = 'Graphics\\Actions\\vegetarianhover.gif'),
PhotoImage(file = 'Graphics\\Actions\\vegetariandown.gif'))
self.img_nextcustomer = (PhotoImage(file = 'Graphics\\Actions\\nextcustomerup.gif'),
PhotoImage(file = 'Graphics\\Actions\\nextcustomerhover.gif'),
PhotoImage(file = 'Graphics\\Actions\\nextcustomerdown.gif'))
level1commands = ['if customer_is_red:\n\tserve pepperoni', 'if customer_is_blue:\n\tserve hawaiian']
level1customers = [('red'), ('green')] #make this a dict corresponding to image too?
level1answers = [('pepperoni'), ('next')]
level1actions = {'pepperoni': self.img_pepperoni , 'hawaiian':self.img_hawaiian, 'vegetarian': self.img_vegetarian,
'next': self.img_nextcustomer}
self.levelscommands = [level1commands]
self.levelscustomers = [level1customers]
self.levelsanswers = [level1answers]
self.levelsactions = [level1actions]
class Customer():
def __init__(self, **attributes):
for k,v in attributes:
self.k = v
#--------------------------------
# Animations
#--------------------------------
class Animation():
def __init__(self, container, pos, images, framerate):
self.container = container
self.x = pos[0]
self.y = pos[1]
self.images = copy(images)
self.imagescopy = copy(images)
self.framerate = framerate # ms between frames
self.done = False
def animate(self):
if len(self.images)>0:
print "animating", len(self.images), self.images
self.container.delete("currentframe") # won't throw an error if non-existant
print self.images[0], "image name"
image = PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready1.gif')
print image, "image"
self.container.create_image(self.x, self.y, image = image, tag = "currentframe")
self.animation = self.container.after(self.framerate, self.animate)
else:
print "finished"
self.container.delete("currentframe")
self.container.after_cancel(self.animation)
self.done = True
def resetAnimation(self):
self.done = False
self.images = copy(self.imagescopy)
#-------------------------
# GUI classes
#-------------------------
class PlayArea():
def __init__(self):
self.window = Tk()
self.window.title("Pizza Program!")
#------------------------------------------------------------
# Initialize player, controller, levels and customer classes
#------------------------------------------------------------
self.player = Player()
self.controller = Controller()
self.levels = Levels()
self.customer = Customer()
#---------------------
# Button and background images
#---------------------
self.img_buttonstart = (PhotoImage(file = 'Graphics\\Controller\\button_startup.gif'),
PhotoImage(file = 'Graphics\\Controller\\button_starthover.gif'),
PhotoImage(file = 'Graphics\\Controller\\button_startdown.gif'))
self.img_buttonpause = (PhotoImage(file = 'Graphics\\Controller\\button_pauseup.gif'),
PhotoImage(file = 'Graphics\\Controller\\button_pausehover.gif'),
PhotoImage(file = 'Graphics\\Controller\\button_pausedown.gif'))
self.img_buttonresume = (PhotoImage(file = 'Graphics\\Controller\\button_resumeup.gif'),
PhotoImage(file = 'Graphics\\Controller\\button_resumehover.gif'),
PhotoImage(file = 'Graphics\\Controller\\button_resumedown.gif'))
self.img_playbgplay = Image.open("Graphics\\PlayArea\\bgplay.gif")
self.img_playbgready = Image.open("Graphics\\PlayArea\\bgready.gif")
# self.imgs_playbgready = [PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready1.gif'),
# PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready2.gif'),
# PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready3.gif'),
# PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready4.gif'),
# PhotoImage(file = 'Graphics\\PlayArea\\ani_bgready5.gif') ]
#-----------------------
# Animations
#-----------------------
self.imgs_playbgready = []
self.imgs_startserving = []
for i in range(1,4):# change later
self.imgs_playbgready.append('Graphics\\PlayArea\\ani_bgready'+str(i)+'.gif')
self.imgs_startserving.append('Graphics\\PlayArea\\ani_startserving'+str(i)+'.gif')
#self.imgs_playbgready = []
#for filename in imgs_playbgready:
# self.imgs_playbgready.append(PhotoImage(file = filename))
#--------------
# Font styles
#--------------
self.controlFont = tkFont.Font(family = "Calibri", size = 10, weight = "bold" )
self.commandFont = tkFont.Font(family = "Courier New", size = 14, weight = "bold")
#-------------------------------------------------------------------------------------------
# Frames to contain the play area (graphics), the command area (what players must do),
# the controller area (start button, timer, score), and action area (possible actions players can take)
#-------------------------------------------------------------------------------------------
self.playFrame = Frame(self.window, bd = 0, highlightthickness = 0)
self.commandFrame = Frame(self.window, bd =0, highlightthickness =0)
self.controlFrame = Frame(self.window, bd =0, highlightthickness =0)
self.actionsFrame = Frame(self.window, bd =0, highlightthickness =0)
self.commandFrame.grid(column = 1, row = 1)
self.playFrame.grid(column = 1, row = 2)
self.controlFrame.grid(column = 2, row = 1)
self.actionsFrame.grid(column = 2, row = 2)
self.actionsFrame.pack_propagate(False)
#self.actionsFrame.columnconfigure(1,weight=1)
#self.window.columnconfigure(2, weight =1)
#-----------------------------------
# Play Area Elements
#-----------------------------------
self.playWidth = 500
self.playHeight = 500
self.playCanvas = Canvas(self.playFrame, width = self.playWidth, height = self.playHeight, bd = -2)
self.playCanvas.pack()
resized = self.img_playbgplay.resize((self.playWidth, self.playHeight), Image.ANTIALIAS)
self.img_playbgplay = ImageTk.PhotoImage(resized)
resized = self.img_playbgready.resize((self.playWidth, self.playHeight), Image.ANTIALIAS)
self.img_playbgready = ImageTk.PhotoImage(resized)
self.playCanvas.create_image(self.playWidth/2, self.playHeight/2, image = self.img_playbgplay)
self.playCanvas.create_image(self.playWidth/2, self.playHeight/2, image = self.img_playbgready,tag = "bgready")
# Bgready animation for when start is pressed
self.ani_playbgready = Animation(self.playCanvas,(self.playWidth/2, self.playHeight/2),self.imgs_playbgready, 5000)
self.ani_startserving = Animation(self.playCanvas,(self.playWidth/2, self.playHeight/2), self.imgs_playbgready,5000)
# Controller elements
# timer and score labels only appear after game starts
self.controlColor = "sky blue"
self.controlWidth = 200
self.controlHeight = 200
self.controllerCanvas = Canvas(self.controlFrame, width = self.controlWidth, height = self.controlHeight, bg = self.controlColor,
bd =0 , highlightthickness =0)
# Frame for containing button, timer and score
self.controlLabelFrame = LabelFrame(self.controllerCanvas, bd = 0, highlightthickness = 0, relief = "ridge", bg = self.controlColor)
#print self.controlLabelFrame.config(), "configs for controlLabelFrame"
self.btStart = Button(self.controlLabelFrame, command = self.startGame, highlightthickness =0, bd =0,
bg = self.controlColor, image = self.img_buttonstart[0])
self.btPause = Button(self.controlLabelFrame, command = self.pauseGame, highlightthickness =0, bd =0,
bg = self.controlColor, image = self.img_buttonpause[0])
self.btResume = Button(self.controlLabelFrame, command = self.resumeGame, highlightthickness =0, bd =0,
bg = self.controlColor, image = self.img_buttonstart[0])
self.controllerCanvas.pack()
self.btStart.grid(row=1, pady = 5)
self.controllerCanvas.create_window(self.controlWidth/2, self.controlHeight/2, window = self.controlLabelFrame)
#Toggle button image
self.changeButtonImage(self.btStart, self.img_buttonstart)
# Timer label
self.timerText = StringVar()
self.timerLabel = Label(self.controlLabelFrame, textvariable = self.timerText, bg = self.controlColor, font = self.controlFont)
self.timerLabel.grid( row = 2, pady=5)
# Level label
self.levelText = StringVar()
self.levelLabel = Label(self.controlLabelFrame, textvariable = self.levelText, bg = self.controlColor, font = self.controlFont)
self.levelLabel.grid( row = 3, pady=5)
# Command elements
self.commandColor = "light sky blue"
self.commandWidth = 500
self.commandHeight = 200
self.commandCanvas = Canvas(self.commandFrame, width = self.commandWidth, height = self.commandHeight, bg = self.commandColor)
self.commandCanvas.pack()
self.commText = StringVar()
self.commLabel = Label(self.commandCanvas, textvariable = self.commText, bg = self.commandColor, font = self.commandFont)
self.commandCanvas.create_window(self.commandWidth/2, self.commandHeight/2, window = self.commLabel)
# Action elements
self.actionColor = "cornflower blue"
self.actionWidth = 200
self.actionHeight = 500
self.actionsFrame.config(width = self.actionWidth, height = self.actionHeight, bg = self.actionColor,)
#self.actionCanvas = Canvas(self.actionsFrame, width = self.actionWidth, height = self.actionHeight, bg = self.actionColor, highlightthickness =0)
#self.actionCanvas.pack()
self.window.mainloop()
#-------------------------------------
# Step methods
# (for checking conditions each step)
#-------------------------------------
def checkAnimation(self, animation, triggerevent, *args):
if not animation.done:
self.window.after(100, self.checkAnimation)
else:
triggerevent(args)
#-------------------------------------
# Controller methods
#-------------------------------------
def changeButtonImage(self, button, images):
def toImage(event, button, image):
button["image"] = image
up, hover, down = images
button.bind("<Enter>", lambda event, button = button, image = hover : toImage(event, button, image))
button.bind("<Leave>", lambda event, button = button, image = up : toImage(event, button, image))
button.bind("<Button-1>", lambda event, button = button, image = down : toImage(event, button, image))
button.bind("<ButtonRelease-1>", lambda event, button = button, image = up : toImage(event, button, image))
def updateController(self):
self.timerText.set("Next Customer: " + str(self.controller.timer))
self.controller.runTimer()
self.update = self.controlFrame.after(1000, self.updateController)
def startGame(self):
#--------------------------
# Update controller elements
#-----------------------------
# Change button
self.btStart.grid_remove()
self.btPause.grid(row=1, pady = 5)
self.changeButtonImage(self.btPause, self.img_buttonpause)
# Timer label
self.timerText.set("Next Customer:" + str(self.controller.timer))
# Level label
self.levelText.set("Level: " + str(self.controller.level))
self.updateController()
#--------------------------------
# Access level commands, customers, answers, and set command display
#--------------------------------
# Commands
self.levelcommands = deepcopy(self.levels.levelscommands[self.controller.level-1]) #copy the list
self.currentcommand = self.levelcommands.pop(0)
self.displayCommand(self.currentcommand)
# Actions
self.levelactions = copy(self.levels.levelsactions[self.controller.level-1])
self.btActions = []
for action, img in self.levelactions.iteritems():
if action != "next":
self.btActions.append(Button(self.actionsFrame, command = self.servePizza,
highlightthickness =0, bd =0, bg = self.actionColor, image = img[0]))
else:
self.btActions.append(Button(self.actionsFrame, command = self.nextCustomer,
highlightthickness =0, bd =0, bg = self.actionColor, image= img[0]))
index = self.btActions.index(self.btActions[-1]) +1
self.btActions[-1].pack(pady = 35)
self.changeButtonImage(self.btActions[-1], img)
# Play Area
self.playCanvas.delete("bgready")
self.ani_playbgready.animate()
#self.checkAnimation(self.ani_playbgready, self.ani_startserving.animate)
self.levelcustomers = deepcopy(self.levels.levelscustomers[self.controller.level-1]) #copy the list
self.currentcustomer = self.levelcustomers.pop(0)
#self.displayCustomer(self.currentcustomer) #need to write this method
# Answers
self.levelanswers = self.levels.levelsanswers[self.controller.level-1][:] # no nested elements
self.currentanswer = self.levelanswers.pop(0)
def pauseGame(self):
#Pause controller updating
# Change button
self.btPause.grid_remove()
self.btResume.grid(row=1, pady = 5)
self.changeButtonImage(self.btResume, self.img_buttonresume)
self.controlFrame.after_cancel(self.update)
def resumeGame(self):
# Resume controller updating
# Change button
self.btResume.grid_remove()
self.btPause.grid(row=1, pady = 5)
self.changeButtonImage(self.btResume, self.img_buttonpause)
self.updateController()
def readyLevel(self):
pass
#---------------------------------
# Command methods
#---------------------------------
def updateCommand(self):
pass
def displayCommand(self, command):
self.commText.set(command)
#--------------------------------
# Action methods
#--------------------------------
def servePizza(self):
pass
def nextCustomer(self):
pass
PlayArea()

Categories