I am making an F1 drivers' application, which gathers API data. The application has designated labels for where specific API content needs to be placed.
What's happening is that whenever I put anything beside a designated label through .grid, the distance between whatever I put and the label is too big. A perfect example of this is in the bottom_left_frame. I've tried different ways (i.e, sticky, padding), but no luck. One way that seems to work is .configure(), but I don't think it's a scalable solution, and I want to place my objects through .grid()
Here's the code. Would appreciate the help!
#import necessary modules
from tkinter import *
from tkinter import ttk
from PIL import ImageTk, Image
from tkinter import messagebox
import requests
import json
root = Tk()
root.title("F1 Desktop Application")
root.geometry("500x600")
root.configure(bg="white")
#NEED TO UNDERSTAND PRECEDENCE BETWEEN WIDTH, HEIGHT SETTING, VS SPANS. STICKY MAKES PERFECT SENSE
top_frame = LabelFrame(root, width = 300, height = 125)
top_frame.grid(row = 0, column = 0, columnspan = 2)
top_frame.rowconfigure(0, minsize = 75)
top_frame.columnconfigure(0, minsize = 300)
header_label = Label(top_frame, text = "F1 2022 Drivers App", font = ("Arial bold",14), bg = "white")
header_label.grid(row = 0, column = 0)
entry= Entry(top_frame)
entry.grid(row = 1, column = 0)
#search_button = Button(top_frame, text = "search")
#search_button.grid(row = 1, column = 1)
left_frame = LabelFrame(root, width = 250, height = 225, borderwidth = 0, highlightthickness = 2)
left_frame.grid(row = 1, column = 0, sticky = NW, padx = 10, pady = 15)
#left_frame.grid_propagate(False)
left_frame.rowconfigure(0, minsize = 100)
left_frame.columnconfigure(0, minsize = 200)
#left_frame_content = LabelFrame(, width = 125, height = 70)
#left_frame_content.grid(row = 1, column = 1, sticky = W)
basic_info = Label(left_frame, text = "Basic Info ", font = ("Arial bold",14))
basic_info.grid(row = 0, column = 0)
full_name = Label(left_frame, text = "Full Name :")
full_name.grid(row = 1, column = 0, sticky = W)
driver_code = Label(left_frame, text = "Driver Code : ")
driver_code.grid(row = 2, column = 0, sticky = W)
nationality = Label(left_frame, text = "Nationality : ")
nationality.grid(row = 3, column = 0, sticky = W)
bottom_left_frame = LabelFrame(root, width = 250, height = 225)
bottom_left_frame.grid(row = 2, column = 0, sticky = N, padx = 10)
bottom_left_frame.rowconfigure(0, minsize = 25)
bottom_left_frame.columnconfigure(0, minsize = 200)
F1_career = Label(bottom_left_frame, text = "F1 Career ", font = ("Arial bold",14))
F1_career.grid(row = 0, column = 0)
wins = Label(bottom_left_frame, text = "Wins :")
wins.grid(row = 1, column = 0, sticky = W)
wins.configure(text = "Wins :" + " 7")
poles = Label(bottom_left_frame, text = "Poles :")
poles.grid(row = 2, column = 0, sticky = W)
test = Label(bottom_left_frame, text = "test")
test.grid(row = 2, column = 1)
podiums = Label(bottom_left_frame, text = "Podiums :")
podiums.grid(row = 3, column = 0, sticky = W)
drivers_championships = Label(bottom_left_frame, text = "Championships :")
drivers_championships.grid(row = 4, column = 0, sticky = W)
bottom_right_frame = LabelFrame(root, width = 250, height = 225)
bottom_right_frame.grid(row = 2, column = 1, sticky = W)
bottom_left_frame.rowconfigure(0, minsize = 50)
bottom_left_frame.columnconfigure(0, minsize = 150)
root.mainloop()
This is my first venture into tkinter programming, so far I have the following code that increases or decreases a number by pressing either button. As you may notice I have started adding an update definition that I'd like to update a results table with the label value each time a button is pressed. I've recently found the lambda expression to add two commands to each button press but can't find an example to build the list:
import tkinter as tk
window = tk.Tk()
def increase():
value = int(lbl_value["text"])
lbl_value["text"] = f"{value + 1}"
def decrease():
value = int(lbl_value["text"])
lbl_value["text"] = f"{value - 1}"
def update():
result_table = []
window.rowconfigure(0, minsize = 100, weight = 1)
window.columnconfigure([0,1,2], minsize = 100, weight = 1)
btn_decrease = tk.Button(master = window, text = "-", command = lambda:[decrease(), update()], bg = 'red', fg = 'white')
btn_decrease.grid(row = 0, column = 0, sticky = "nsew")
lbl_value = tk.Label(master = window, text = "0")
lbl_value.grid(row = 0, column = 1)
btn_increase = tk.Button(master = window, text = "+", command = lambda:[increase(), update()], bg = 'green', fg = 'white')
btn_increase.grid(row = 0, column = 2, sticky = "nsew")
window.mainloop()
, bg = 'black', fg = 'white')
btn_decrease.grid(row = 0, column = 0, sticky = "nsew")
lbl_value = tk.Label(master = window, text = "0")
lbl_value.grid(row = 0, column = 1)
btn_increase = tk.Button(master = window, text = "+", command = increase, bg = 'red', fg = 'white')
btn_increase.grid(row = 0, column = 2, sticky = "nsew")
window.mainloop()
I'd like to add a graph of the count to the display ultimately. Any help greatly appreciated.
Matt
I cannot for the life in me work out why this does not work. I am using TKinter to display an image in Python. The code I have written so far is shown here:
from tkinter import *
from tkinter import messagebox
def unlock():
root.withdraw()
def logout():
inside.destroy()
root.deiconify()
#######################
### ###
### unlock Form ###
### ###
#######################
inside = Tk()
inside.geometry("576x576")
inside.title("SAFE CRACKER")
# LABELS, Textboxes and Buttons
imageInside = PhotoImage(file = "images/inside.gif")
imageLabel = Label(inside,image = imageInside).grid(row =1, columnspan = 2)
label = Label(inside, text="Safe Cracker", font = ("Arial",16)).grid(row = 0, columnspan = 2)
exitButton = Button(inside, text = "Exit", width = 15, command = logout )
exitButton.grid(row = 3, column = 0,padx = 10, pady = 10)
#######################
### ###
### Main Form ###
### ###
#######################
root = Tk()
root.geometry("430x450")
root.title("SAFE CRACKER")
# LABELS, Textboxes and Buttons
label = Label(root, text="Safe Cracker", font = ("Arial",16)).grid(row = 0, columnspan = 2)
imageSafe = PhotoImage(file = "images/safe.gif")
imageLabel = Label(root,image = imageSafe).grid(row =1, columnspan = 2)
label = Label(root, text = "Enter the code", font = ("Arial",12)).grid(row = 2, column = 0)
unlockCode = Entry(root, width = 30)
unlockCode.grid(row = 2, column = 1,padx = 10, pady = 10)
exitButton = Button(root, text = "Exit", width = 15, command = exit).grid(row = 3, column = 0,padx = 10, pady = 10)
enterButton = Button(root, text = "Enter the VAULT", width = 15, command = unlock).grid(row = 3, column = 1,padx = 10, pady = 10)
The code doesn't do much at present, however it's something i'm working on. When I run the program it will display a picture of a safe (Great), and when I click the button it moves over to the next form.
image of safe working
On the new form the image, labels and buttons do not display, however, when the image code is removed it all works swimmingly.
Initially I thought about putting the root form within a function, however, whenever I place this code within a function it fails to load the image (ahhhh). Can these images not be placed within functions?
You need to keep a reference to the photo.
imageInside = PhotoImage(file = "images/inside.gif")
imageLabel = Label(inside,image = imageInside)
imageLabel.grid(row =1, columnspan = 2)
imageLabel.photo_ref = imageInside # keep a reference!
Thank you for your help.
I can confirm that this works, here's the code.
from tkinter import *
from tkinter import messagebox
def unlock():
root.withdraw()
def logout():
inside.destroy()
root.deiconify()
#######################
### ###
### unlock Form ###
### ###
#######################
inside = Toplevel()
inside.geometry("576x576")
inside.title("SAFE CRACKER")
# LABELS, Textboxes and Buttons
imageInside = PhotoImage(file = "images/inside.gif")
imageLabel = Label(inside,image = imageInside)
imageLabel.grid(row =1, columnspan = 2)
imageLabel.photo_ref = imageInside
label = Label(inside, text="Safe Cracker", font = ("Arial",16)).grid(row = 0, columnspan = 2)
exitButton = Button(inside, text = "Exit", width = 15, command = logout )
exitButton.grid(row = 3, column = 0,padx = 10, pady = 10)
#######################
### ###
### Main Form ###
### ###
#######################
root = Tk()
root.geometry("430x450")
root.title("SAFE CRACKER")
# LABELS, Textboxes and Buttons
label = Label(root, text="Safe Cracker", font = ("Arial",16)).grid(row = 0, columnspan = 2)
imageSafe = PhotoImage(file = "images/safe.gif")
imageLabel = Label(root,image = imageSafe).grid(row =1, columnspan = 2)
label = Label(root, text = "Enter the code", font = ("Arial",12)).grid(row = 2, column = 0)
unlockCode = Entry(root, width = 30)
unlockCode.grid(row = 2, column = 1,padx = 10, pady = 10)
exitButton = Button(root, text = "Exit", width = 15, command = exit).grid(row = 3, column = 0,padx = 10, pady = 10)
enterButton = Button(root, text = "Enter the VAULT", width = 15, command = unlock).grid(row = 3, column = 1,padx = 10, pady = 10)
This script when run, opens a window that is divided into 3 frames:
A big frame into which data will be shown (label widgets).
A smaller frame underneath it with user input widgets.
A small frame in the bottom-right corner with a textbox widget.
The big frame will have a lot of data (= label-widgets) so I need it to be scrollable (vertically).
This I have done by creating a canvas widget alonside a scrollbar widget. In the canvas, a frame widget is placed.
Everything seems to be working, however my resizing function does not.
My frame widget does not get its dimensions updated! This is probably because of an error that I can't manage to fix.
Fundamental question:
The script gives an error on the "lambda: resize_frame(self)" command on line 43. How do i fix this?
Side-note: My issue probably has more to do with an improper binding on the canvas widget. Because I'm not sure I wanted to give enough context (script).
Many thanks in advance.
from Tkinter import *
import math
class Processing(Toplevel):
def __init__(self, master, *args, **kwargs):
Toplevel.__init__(self, master)
self.master = master
self.title("Process Window")
for r in range(6):
self.rowconfigure(r, weight = 1)
for c in range(4):
self.columnconfigure(c, weight = 1)
### WINDOW size and position definitions ###
ScreenSizeX = master.winfo_screenwidth()
ScreenSizeY = ( master.winfo_screenheight() - 75 ) #about 75pixels for taskbar on bottom of screen (Windows)
ScreenRatio = 0.9
FrameSizeX = int(ScreenSizeX * ScreenRatio)
FrameSizeY = int(ScreenSizeY * ScreenRatio)
FramePosX = (ScreenSizeX - FrameSizeX)/2
FramePosY = (ScreenSizeY - FrameSizeY)/2
self.geometry("%sx%s+%s+%s"%(FrameSizeX,FrameSizeY,FramePosX,FramePosY))
### Creating 3 "sub-frames" ###
# Frame 1 - canvas container with scrollbar#
self.Canvas1 = Canvas(self, bg = "white")
self.Canvas1.grid(row = 0, column = 0, rowspan = 5, columnspan = 4, sticky = N+E+S+W)
self.Canvas1.rowconfigure(1, weight = 1)
self.Canvas1.columnconfigure(1, weight = 1)
self.myscrollbar=Scrollbar(self, orient = "vertical", command = self.Canvas1.yview)
self.Canvas1.configure(yscrollcommand = self.myscrollbar.set)
self.myscrollbar.grid(row = 0, column = 4, rowspan = 5, sticky = N+S)
# Frame 1 - Frame widget in canvas #
self.Frame1 = Frame(self.Canvas1, bg = "white")
self.Frame1.rowconfigure(0, weight = 1)
for c in range(2):
self.Frame1.columnconfigure(1 + (2 * c), weight = 1)#1,3 - columns for small icons in the future
for cb in range(3):
self.Frame1.columnconfigure((cb * 2), weight = 9)#0,2,4 - columns for data
self.CFrame1 = self.Canvas1.create_window(0, 0, window = self.Frame1, width = FrameSizeX, anchor = N+W)
self.Canvas1.bind("<Configure>", lambda: resize_frame(self)) # !!!!! Doesn't work & gives error !!!!!! #
self.Frame1.bind("<Configure>", lambda: scrollevent(self))
self.Canvas1.config(scrollregion=self.Canvas1.bbox("all"))
# Frame 2 #
self.Frame2 = Frame(self, bg= "yellow")
self.Frame2.grid(row = 5, column = 0, rowspan = 1, columnspan = 3, sticky = W+E+N+S)
for r in range(3):
self.Frame2.rowconfigure(r, weight=1)
for c in range(3):
self.Frame2.columnconfigure(c, weight = 1)
# Frame 3 #
self.Frame3 = Frame(self)
self.Frame3.grid(row = 5, column = 3, rowspan = 1, columnspan = 2, sticky = W+E+N+S)
self.Frame3.rowconfigure(0, weight = 1)
self.Frame3.columnconfigure(0, weight = 1)
# Propagation #
#self.grid_propagate(False) # All widgets (the 3 subframes) need to fit in Toplevel window. Minimal window size will be implemented later.
self.Canvas1.grid_propagate(False) # canvas works with scrollbar, widgets dont need to fit in window size.
#self.Frame1.grid_propagate(False) # Frame1 should resize to hold all data (label-widgets)
self.Frame2.grid_propagate(False) # fixed frame dimensions
self.Frame3.grid_propagate(False) # fixed textbox dimensions
self.Frame1.update_idletasks() # just to make sure
### Widgets for the multiple frames ###
# Frame1 - further populated by button command in frame 2#
self.lblaa = Label(self.Frame1, bg="white", text = "Processing...", justify = "left")
self.lblaa.grid(row = 0, column = 0, sticky = N+W)
self.LSlabelsr = []
self.LSlabelsa = []
self.LSlabelsb = []
# Frame 2 #
self.Wbuttontest=Button(self.Frame2, text="Start listing test", command = lambda: refresh(self))
self.Wbuttontest.grid(row = 0, column = 0, columnspan = 3)
self.Wentry = Entry(self.Frame2)
self.Wentry.grid(row = 2, column = 0, columnspan = 3, sticky = E+W, padx = 10)
self.Wentry.delete(0, END)
self.Wentry.insert(0, "user input here")
# Frame3 #
self.Wtext = Text(self.Frame3)
self.Wscrollb = Scrollbar(self.Frame3)
self.Wscrollb.config(command = self.Wtext.yview)
self.Wtext.config(yscrollcommand = self.Wscrollb.set)
self.Wtext.grid(row = 0, column = 0, sticky = N+E+W+S)
### Test-Lists ### Last character in the left column is "ez" !! ###
self.LSa = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
self.LSb = [1, 2, 3, 4, 66, 6, 7, 8, 9, 67, 11, 12, 13, 14, 68]
self.LSr = []
ib = 0
prefix = ""
for i in range(104):
if ib > 25:
prefix = chr(ord("a") + (i/ib - 1))
ib = 0
else:
pass
self.LSr.append(prefix + chr(97+ib))
ib += 1
### FUNCTIONS ###
def resize_frame(self, event):
self.Canvas1.itemconfig(self.CFrame1, width = e.width) #height of frame should depend on the contents.
def scrollevent(event):
self.Canvas1.configure(scrollregion=self.Canvas1.bbox("all"),width=200,height=200)
def refresh(self): ### Button-command: data will be shown ###
if self.lblaa.winfo_exists() == 1:
self.lblaa.destroy()
for i in range(len(self.LSr)):
self.Frame1.rowconfigure(i, weight = 0)
del self.LSlabelsr[:] # remove any previous labels from if the callback was called before
del self.LSlabelsa[:] # remove any previous labels from if the callback was called before
del self.LSlabelsb[:] # remove any previous labels from if the callback was called before
Vlabelheight = 1
# Left List #
for i in range(len(self.LSr)):
self.LSlabelsr.append(Label(self.Frame1, text = str(self.LSr[i]), bg = "LightBlue", justify = "left", height = Vlabelheight))
self.LSlabelsr[i].grid(row = i, column = 0, sticky = E+W)
# Middle List #
for i in range(len(self.LSa)):
self.LSlabelsa.append(Label(self.Frame1, text = str(self.LSa[i]), bg = "LightBlue", fg = "DarkViolet", justify = "left", height = Vlabelheight))
self.LSlabelsa[i].grid(row = i, column = 2, sticky = E+W)
# Right List #
for i in range(len(self.LSb)):
self.LSlabelsb.append(Label(self.Frame1, text = str(self.LSb[i]), bg = "LightBlue", fg = "DarkGreen", justify = "left", height = Vlabelheight))
self.LSlabelsb[i].grid(row = i, column = 4, sticky = E+W)
self.Frame1.update()
self.Frame1.update_idletasks()
print("done")
if __name__ == "__main__":
root = Tk()
root.title("Invisible")
root.resizable(FALSE,FALSE)
root.withdraw()
app = Processing(root)
root.mainloop()
Working version after suggestions by R4PH4EL:
Proper indentation: the functions were defined as part of the init.
Some tweaks on the lambda commands on line 43/107 & 44/110.
from Tkinter import *
import math
class Processing(Toplevel):
def __init__(self, master, *args, **kwargs):
Toplevel.__init__(self, master)
self.master = master
self.title("Process Window")
for r in range(6):
self.rowconfigure(r, weight = 1)
for c in range(4):
self.columnconfigure(c, weight = 1)
### WINDOW size and position definitions ###
ScreenSizeX = master.winfo_screenwidth()
ScreenSizeY = ( master.winfo_screenheight() - 75 ) #about 75pixels for taskbar on bottom of screen (Windows)
ScreenRatio = 0.9
FrameSizeX = int(ScreenSizeX * ScreenRatio)
FrameSizeY = int(ScreenSizeY * ScreenRatio)
FramePosX = (ScreenSizeX - FrameSizeX)/2
FramePosY = (ScreenSizeY - FrameSizeY)/2
self.geometry("%sx%s+%s+%s"%(FrameSizeX,FrameSizeY,FramePosX,FramePosY))
### Creating 3 "sub-frames" ###
# Frame 1 - canvas container with scrollbar#
self.Canvas1 = Canvas(self, bg = "white")
self.Canvas1.grid(row = 0, column = 0, rowspan = 5, columnspan = 4, sticky = N+E+S+W)
self.Canvas1.rowconfigure(1, weight = 1)
self.Canvas1.columnconfigure(1, weight = 1)
self.myscrollbar=Scrollbar(self, orient = "vertical", command = self.Canvas1.yview)
self.Canvas1.configure(yscrollcommand = self.myscrollbar.set)
self.myscrollbar.grid(row = 0, column = 4, rowspan = 5, sticky = N+S)
# Frame 1 - Frame widget in canvas #
self.Frame1 = Frame(self.Canvas1, bg = "white")
self.Frame1.rowconfigure(0, weight = 1)
for c in range(2):
self.Frame1.columnconfigure(1 + (2 * c), weight = 1)#1,3 - columns for small icons in the future
for cb in range(3):
self.Frame1.columnconfigure((cb * 2), weight = 9)#0,2,4 - columns for data
self.CFrame1 = self.Canvas1.create_window(0, 0, window = self.Frame1, width = FrameSizeX, anchor = N+W)
self.Canvas1.bind("<Configure>", lambda event: self.resize_frame(event)) # !!!!! Doesn't work & gives error !!!!!! #
self.Frame1.bind("<Configure>", lambda event: self.scrollevent(event))
self.Canvas1.config(scrollregion=self.Canvas1.bbox("all"))
# Frame 2 #
self.Frame2 = Frame(self, bg= "yellow")
self.Frame2.grid(row = 5, column = 0, rowspan = 1, columnspan = 3, sticky = W+E+N+S)
for r in range(3):
self.Frame2.rowconfigure(r, weight=1)
for c in range(3):
self.Frame2.columnconfigure(c, weight = 1)
# Frame 3 #
self.Frame3 = Frame(self)
self.Frame3.grid(row = 5, column = 3, rowspan = 1, columnspan = 2, sticky = W+E+N+S)
self.Frame3.rowconfigure(0, weight = 1)
self.Frame3.columnconfigure(0, weight = 1)
# Propagation #
#self.grid_propagate(False) # All widgets (the 3 subframes) need to fit in Toplevel window. Minimal window size will be implemented later.
self.Canvas1.grid_propagate(False) # canvas works with scrollbar, widgets dont need to fit in window size.
#self.Frame1.grid_propagate(False) # Frame1 should resize to hold all data (label-widgets)
self.Frame2.grid_propagate(False) # fixed frame dimensions
self.Frame3.grid_propagate(False) # fixed textbox dimensions
self.Frame1.update_idletasks() # just to make sure
### Widgets for the multiple frames ###
# Frame1 - further populated by button command in frame 2#
self.lblaa = Label(self.Frame1, bg="white", text = "Processing...", justify = "left")
self.lblaa.grid(row = 0, column = 0, sticky = N+W)
self.LSlabelsr = []
self.LSlabelsa = []
self.LSlabelsb = []
# Frame 2 #
self.Wbuttontest=Button(self.Frame2, text="Start listing test", command = lambda: self.refresh())
self.Wbuttontest.grid(row = 0, column = 0, columnspan = 3)
self.Wentry = Entry(self.Frame2)
self.Wentry.grid(row = 2, column = 0, columnspan = 3, sticky = E+W, padx = 10)
self.Wentry.delete(0, END)
self.Wentry.insert(0, "user input here")
# Frame3 #
self.Wtext = Text(self.Frame3)
self.Wscrollb = Scrollbar(self.Frame3)
self.Wscrollb.config(command = self.Wtext.yview)
self.Wtext.config(yscrollcommand = self.Wscrollb.set)
self.Wtext.grid(row = 0, column = 0, sticky = N+E+W+S)
### Test-Lists ### Last character in the left column is "ez" !! ###
self.LSa = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
self.LSb = [1, 2, 3, 4, 66, 6, 7, 8, 9, 67, 11, 12, 13, 14, 68]
self.LSr = []
ib = 0
prefix = ""
for i in range(104):
if ib > 25:
prefix = chr(ord("a") + (i/ib - 1))
ib = 0
else:
pass
self.LSr.append(prefix + chr(97+ib))
ib += 1
### FUNCTIONS ###
def resize_frame(self, e):
self.Canvas1.itemconfig(self.CFrame1, width = e.width) #height of frame should depend on the contents.
def scrollevent(self, event):
self.Canvas1.configure(scrollregion=self.Canvas1.bbox("all"),width=200,height=200)
def refresh(self): ### Button-command: data will be shown ###
if self.lblaa.winfo_exists() == 1:
self.lblaa.destroy()
for i in range(len(self.LSr)):
self.Frame1.rowconfigure(i, weight = 0)
del self.LSlabelsr[:] # remove any previous labels from if the callback was called before
del self.LSlabelsa[:] # remove any previous labels from if the callback was called before
del self.LSlabelsb[:] # remove any previous labels from if the callback was called before
Vlabelheight = 1
# Left List #
for i in range(len(self.LSr)):
self.LSlabelsr.append(Label(self.Frame1, text = str(self.LSr[i]), bg = "LightBlue", justify = "left", height = Vlabelheight))
self.LSlabelsr[i].grid(row = i, column = 0, sticky = E+W)
# Middle List #
for i in range(len(self.LSa)):
self.LSlabelsa.append(Label(self.Frame1, text = str(self.LSa[i]), bg = "LightBlue", fg = "DarkViolet", justify = "left", height = Vlabelheight))
self.LSlabelsa[i].grid(row = i, column = 2, sticky = E+W)
# Right List #
for i in range(len(self.LSb)):
self.LSlabelsb.append(Label(self.Frame1, text = str(self.LSb[i]), bg = "LightBlue", fg = "DarkGreen", justify = "left", height = Vlabelheight))
self.LSlabelsb[i].grid(row = i, column = 4, sticky = E+W)
self.Frame1.update()
self.Frame1.update_idletasks()
print("done")
if __name__ == "__main__":
root = Tk()
root.title("Invisible")
root.resizable(FALSE,FALSE)
root.withdraw()
app = Processing(root)
root.mainloop()
Either your indentation is wrong or your getting something wrong in general.
All of your functions are defined inside your __init__ function
Second: if you want to call a class function, you call it by obj.function
Your error on lambda: resize(self) may occur as it should be lambda: self.resize.
Give it a shot with this one and try it.
And please make sure your indentations are correct.
I totally agree with Bryan here - ommiting the lambdas it would be (my personal opinion) easier to read and kind of "better" in a meaning of more structured and pragmatic coding style.