How to make a background image not cover labels in tkinter - python

I am making a simple maths game but my background is covering the labels
how do I make it so the background image still resizes to the screen but is under the labels instead?
this is my code:
import tkinter
from tkinter import *
import tkinter.font as font
from PIL import Image, ImageTk
# INITIALIZE TKINTER
root = tkinter.Tk()
root.title('Test De Multiplications')
#root.iconbitmap('')
root.geometry('600x400')
# DEFINE FONTS
labelfont = font.Font(family='Comic Sans MS', weight='bold', size='30')
normalfont = font.Font(family='Arial', size='20')
subtitle = font.Font(family='Calibri', weight='bold', size='25')
# RAISING FRAMES (Swithching windows)
def raise_frame(frame):
frame.tkraise()
f1 = Frame(root)
f2 = Frame(root)
for frame in (f1, f2):
frame.grid(row=0, column=0, sticky='news')
title = Label(f1, text="TEST DE MULTIPLICATIONS", font=labelfont)
title.pack(side= TOP, fill = BOTH, expand = True)
start = Button(f1, text='Commencer', font=normalfont, background='darkred', command=lambda:raise_frame(f2))
start.pack(side= TOP, expand= True)
playtitle = Label(f2, text='QUESTION:', font=normalfont ).pack()
raise_frame(f1)
class bg(Frame):
def __init__(self, master, *pargs):
Frame.__init__(self, master, *pargs)
self.image = Image.open("bg.ppm")
self.img_copy= self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = Label(self, image=self.background_image)
self.background.pack(fill=BOTH, expand=YES)
self.background.bind('<Configure>', self._resize_image)
def _resize_image(self,event):
new_width = event.width
new_height = event.height
self.image = self.img_copy.resize((new_width, new_height))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image = self.background_image)
e = bg(root)
e.place(x=0, y=0, relwidth=1, relheight=1)
root.mainloop()
I'm using multiple frames for the window switching so I'm wondering if that has something to do with it? I still want to be able to change windows like this, because it works well.

Related

Why am I getting a value error in imagegrab pil?

So I am making an Tkinter painting application but I keep getting a Value:Error which is blocking me from proceeding and I don't know how to solve it.
here is my code
from tkinter import *
from tkinter import Scale
from tkinter import colorchooser, filedialog, messagebox
import PIL.ImageGrab as ImageGrab
class Paint(): # the class adds the screen for all the widgets to be added on
def __init__(self,root):
global color
self.root = root
self.root.title("Paint")
self.root.geometry("800x520")
self.root.configure(background='white')
self.root.resizable(100,100)
self.pen_color ="black"
self.eraser_color = "white"
# Adding the widgets
self.color_frame = LabelFrame(self.root, text='Color Palette', font=("Lucida's Caligraphy",15),bd=10, relief=RIDGE, bg='pink')
self.color_frame.place(x=0,y=0,width=145,height=190)
colors = ["#ff00ff", "#ff0000", "#ffa600", "#ffff00", "#80ff80", "#00ff00", "#09ff90", "#0ff8c0", "#00d0ff", "#00ffff", "#ffffff", "#fff3d4", "#808080", "#404040", "#202020", "#000000"]
i=j=0
for color in colors: # this is the creation for the positioning of the colors
Button(self.color_frame,bg=color,bd=2,relief=RIDGE,width=3,command=lambda col=color:self.select_color(col)).grid(row=i,column=j) # this is the creation for the color buttons
i+=1
if i==4:
i=0
j+=1
self.eraser_button = Button(self.root,text='Eraser',bg='violet',bd=2,relief=GROOVE,width=3,command=self.eraser) # this is the creation for the eraser button
self.eraser_button.place(x=0, y=187, width=60, height=30)
self.clear_button = Button(self.root,text='Clear',bg='light blue',bd=2,relief=GROOVE,width=3,command=lambda : self.canvas.delete("all")) # this is the creation for the clear button
self.clear_button.place(x=0, y=217, width=60, height=30)
self.save_button = Button(self.root,text='Save',bg='light green',bd=2,relief=GROOVE,width=3,command=self.save_paint) # this is the creation for the save button
self.save_button.place(x=0, y=247, width=60, height=30)
self.canvas_button = Button(self.root,text="Canvas",bg='light cyan', bd=4, width=8,relief=GROOVE,command=self.canvas_color) # this is the creation for the canvas button
self.canvas_button.place(x=0, y=277)
self.pen_scale_frame = LabelFrame(self.root,text='size', bg='white', bd=5, font=('arial', 15), relief=RIDGE,) # this is the creation for the box that contains the colors
self.pen_scale_frame.place(x=0, y=310, width=70, height=200)
self.pen_scale = Scale(self.pen_scale_frame, orient=VERTICAL,from_=100, to=0,length=150) # this is the creation for the scale
self.pen_scale.set(1)
self.pen_scale.place(x=5,y=10)
self.canvas = Canvas(self.root, bg='light cyan', bd=4, relief=GROOVE, width=1105, height=630) # this is the creation for the canvas
self.canvas.place(x=150, y=0)
self.canvas.bind("<B1-Motion>",self.paint) # this binds the mouse motion with the canvas
def paint(self,event): # this is the function for the ink to be shown on the canvas
x1,y1 = (event.x-0),(event.y-0)
x2,y2 = (event.x+0), (event.y+0)
self.canvas.create_oval(x1,y1,x2,y2,fill=self.pen_color,outline=self.pen_color,width=self.pen_scale.get())
def select_color(self, col): # this is the function for selecting colors for my pen
self.pen_color = col
def eraser(self): # this is the function for copying the colors that my canvas has for my eraser
self.pen_color = self.eraser_color
def canvas_color(self): # this is the function for selecting colors for my canvas
color = colorchooser.askcolor()
self.canvas.configure(background=color[1])
self.eraser_color = color[1]
self.pen_color = color[1]
def save_paint(self): # this is the function for screenshotting whatever is on the canvas
global filename
filename = filedialog.asksaveasfilename(initialdir='C:/',filetypes=[('All files','.*'), ('Picture Files','.png*')])
print(filename)
cx = self.root.winfo_rootx() + self.canvas.winfo_x()
print(cx, self.root.winfo_rootx())
cy = self.root.winfo_rooty() + self.canvas.winfo_y()
print(cy)
cx1 = cx + self.canvas.winfo_width()
print(cx1)
cy1 = cy + self.canvas.winfo_height()
print(cy1)
filename = filename + '.jpeg'
ImageGrab.grab().crop((cx1, cy1, cx, cy)).save(filename) # <-- The value:Error redirects me here
messagebox.showinfo('paint sys','image is saved as '+ str(filename))
if __name__ == "__main__":
root = Tk()
p = Paint(root)
root.mainloop()
the error
**ImageGrab.grab().crop((cx1, cy1, cx, cy)).save(filename) line 1171, in crop
raise ValueError("Coordinate 'right' is less than 'left'")
ValueError: Coordinate 'right' is less than 'left'
**
Whats wrong with my code?

Is there any way to make tkinter Radiobutton transparent on tkinter canvas?

I want to make radiobutton transparent on canvas image to make it look good, I tried passing lots of option parameters to radiobutton to somehow make it look better but nothing works.
Here is the code I am working with...
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
from PIL import ImageTk, Image
from tkinter import messagebox
class GUI_Prog:
def __init__(self):
root = Tk()
root.title("Risk Analysis")
root.geometry("1100x630")
r = IntVar()
#Setting up Canvas :
my_canvas = Canvas(root, width=1100, height=630)
my_canvas.pack(fill="both", expand=True)
#Background :
img = Image.open("diagnosis.png")
img = img.resize((1100,630), Image.ANTIALIAS)
bg = ImageTk.PhotoImage(img)
my_canvas.create_image(0,0,image=bg,anchor="nw")
#Creating title text :
my_canvas.create_text(540,40,text="Risk Analysis", font=("Times, 30"), fill = "white")
my_canvas.create_text(140,100,text="1) Do you smoke?", font=("helvetica, 15"), fill = "black")
but_1 = Radiobutton(root, text="yes", variable=r, value=1)
my_canvas.create_window(60, 150, window=but_1)
but_2= Radiobutton(root, text="no", variable=r, value=2)
my_canvas.create_window(150, 150, window=but_2)
mainloop()
obj = GUI_Prog()
Well I created my own RadioButton class but it only works on tkinter.Canvas:
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
from PIL import ImageTk, Image
from tkinter import messagebox
# Taken from: https://stackoverflow.com/a/17985217/11106801
def _create_circle(self, x, y, r, **kwargs):
return self.create_oval(x-r, y-r, x+r, y+r, **kwargs)
Canvas.create_circle = _create_circle
class Radiobutton:
def __init__(self, canvas, text="", variable=None, value=0, radius=10,
fill="black"):
self.canvas = canvas
self.variable = variable
self.fill = fill
self.text = text
self.value = value
self.radius = radius
self.variable.trace("w", self.redraw)
self.circle = None
def put(self, x, y):
self.x = x
self.y = y
self.canvas.create_circle(x, y, self.radius, outline=self.fill)
self.canvas.create_text(x + 2*self.radius, y, text=self.text,
fill=self.fill, anchor="w")
self.redraw()
self.canvas.bind("<Button-1>", self.select, add=True)
def select(self, event):
if (self.x - event.x)**2 + (self.y - event.y)**2 <= self.radius**2:
self.variable.set(self.value)
self.redraw()
def create_circle(self):
self.circle = self.canvas.create_circle(self.x, self.y, self.radius-4,
outline=self.fill,
fill=self.fill)
def redraw(self, *args):
if self.value == self.variable.get():
if self.circle is None:
self.create_circle()
else:
if self.circle is not None:
self.canvas.delete(self.circle)
self.circle = None
class GUI_Prog:
def __init__(self):
root = Tk()
root.title("Risk Analysis")
root.geometry("1100x630")
r = IntVar()
#Setting up Canvas:
my_canvas = Canvas(root, width=1100, height=630)
my_canvas.pack(fill="both", expand=True)
#Background:
img = Image.open("diagnosis.png")
img = img.resize((1100, 630), Image.ANTIALIAS)
bg = ImageTk.PhotoImage(img)
my_canvas.create_image(0, 0, image=bg, anchor="nw")
#Creating title text:
my_canvas.create_text(540, 40, text="Risk Analysis",
font=("Times", 30), fill="white")
my_canvas.create_text(140, 100, text="1) Do you smoke?",
font=("helvetica", 15), fill="black")
but_1 = Radiobutton(my_canvas, text="yes", variable=r, value=1,
fill="white")
but_1.put(60, 150)
but_2 = Radiobutton(my_canvas, text="no", variable=r, value=2,
fill="white")
but_2.put(150, 150)
r.set(1)
root.mainloop()
obj = GUI_Prog()
You create it as normal but you pass in the <tkinter.Canvas> as its master. After that you can just call .put with the position where you want it to be created. This is a very patchy solution so if someone else posts a better solution, I will delete this.

Need to Add a Scroll Toolbar to FGCs LabelFrame (Tkinter)

Working on an internal app and trying to get a scrollbar to "FGCs" labelFrame only, in addition, I need to scale the frame to the app size.
I'll be happy if anyone could assist me in refactoring this and create the scrollbar.
I know that I need to create a canvas or something, but do not know how.
This is a first time for me with Tkinter.
from tkinter import *
import os, subprocess
from tkinter import ttk
managment = ["MAIN","NAV","OUTPUT","OUTPUTSPARE","GATEWAY","Sync1","Sync2"]
servers = ["recon01","recon02","recon03","recon04","recon05","recon06","recon07","recon08","recon09","recon10","recon11","recon12","render01","render02","storinator"]
FGCs =["fgc01","fgc02","fgc03","fgc04","fgc05","fgc06","fgc07","fgc08","fgc09","fgc10","fgc11","fgc12","fgc13","fgc14","fgc15","fgc16","fgc17","fgc18","fgc19","fgc20","fgc21","fgc22","fgc23","fgc24","fgc25","fgc26","fgc27","fgc28","fgc29","fgc30","fgc31","fgc32","fgc33","fgc34","fgc35","fgc36","fgc37","fgc38","fgcspare1","fgcspare2","fgcspare3","fgcspare4"]
tests = ["Network", "GPU", "Time", "Gidel", "Snapshot", "Disks"]
testbuttons = []
serverbuttons = []
managebuttons = []
fgcbuttons = []
class mainwindow:
global test
global testbuttons
global managment
global managebuttons
global FGCs
def __init__(self,master):
self.master = master
master.title("System Report Tool")
master.geometry("1000x500")
self.Tests = ttk.LabelFrame(root, text="Tests")
self.Tests.pack(expand="no",anchor=W,pady=20)
for test in tests:
testcheck = ttk.Checkbutton(self.Tests, text=test)
testcheck.pack(side=LEFT, anchor="n")
testbuttons.append(testcheck)
def select_tests():
for test in testbuttons:
test.invoke()
selecttests = ttk.Checkbutton(root, text="Select All",command=select_tests)
selecttests.place(x=260,y=16)
self.Managment = ttk.LabelFrame(root, text="Managment")
self.Managment.configure(width=10, height=20)
self.Managment.pack(expand="no",anchor=W)
for manage in managment:
managecheck = ttk.Checkbutton(self.Managment, text=manage)
managecheck.pack(side=TOP, anchor="w")
managebuttons.append(managecheck)
def select_manage():
for manage in managebuttons:
manage.invoke()
selectmanage = ttk.Checkbutton(self.Managment, text="Select All",command=select_manage)
selectmanage.pack()
self.FGCs = ttk.LabelFrame(root, text="FGCs")
self.FGCs.configure(width=10, height=20)
self.FGCs.place(x=120,y=80)
for fgc in FGCs:
fgccheck = ttk.Checkbutton(self.FGCs, text=fgc)
fgccheck.pack(side=TOP, anchor="w")
fgcbuttons.append(fgccheck)
def select_fgc():
for fgc in fgcbuttons:
fgc.invoke()
selectfgc = ttk.Checkbutton(self.FGCs, text="Select All",command=select_fgc)
selectfgc.pack()
root = Tk()
Window = mainwindow(root)
root.mainloop()
Thanks in advance.
Copy code with class ScrolledFrame from scrolled-frame-canvas
Create ScrolledFrame inside LabelFrame self.FGCs
self.sf = ScrolledFrame(self.FGCs)
self.sf.pack()
And then put widgets in inner element in ScrolledFrame instead of putting them in self.FGCs like
fgccheck = ttk.Checkbutton(self.sf.inner, text=fgc)
Working code
import os
import subprocess
import tkinter as tk
from tkinter import *
from tkinter import ttk
class ScrolledFrame(tk.Frame):
def __init__(self, parent, vertical=True, horizontal=False):
super().__init__(parent)
# canvas for inner frame
self._canvas = tk.Canvas(self)
self._canvas.grid(row=0, column=0, sticky='news') # changed
# create right scrollbar and connect to canvas Y
self._vertical_bar = tk.Scrollbar(self, orient='vertical', command=self._canvas.yview)
if vertical:
self._vertical_bar.grid(row=0, column=1, sticky='ns')
self._canvas.configure(yscrollcommand=self._vertical_bar.set)
# create bottom scrollbar and connect to canvas X
self._horizontal_bar = tk.Scrollbar(self, orient='horizontal', command=self._canvas.xview)
if horizontal:
self._horizontal_bar.grid(row=1, column=0, sticky='we')
self._canvas.configure(xscrollcommand=self._horizontal_bar.set)
# inner frame for widgets
self.inner = tk.Frame(self._canvas)
self._window = self._canvas.create_window((0, 0), window=self.inner, anchor='nw')
# autoresize inner frame
self.columnconfigure(0, weight=1) # changed
self.rowconfigure(0, weight=1) # changed
# resize when configure changed
self.inner.bind('<Configure>', self.resize)
# resize inner frame to canvas size
self.resize_width = False
self.resize_height = False
self._canvas.bind('<Configure>', self.inner_resize)
def resize(self, event=None):
self._canvas.configure(scrollregion=self._canvas.bbox('all'))
def inner_resize(self, event):
# resize inner frame to canvas size
if self.resize_width:
self._canvas.itemconfig(self._window, width=event.width)
if self.resize_height:
self._canvas.itemconfig(self._window, height=event.height)
managment = ["MAIN","NAV","OUTPUT","OUTPUTSPARE","GATEWAY","Sync1","Sync2"]
servers = ["recon01","recon02","recon03","recon04","recon05","recon06","recon07","recon08","recon09","recon10","recon11","recon12","render01","render02","storinator"]
FGCs =["fgc01","fgc02","fgc03","fgc04","fgc05","fgc06","fgc07","fgc08","fgc09","fgc10","fgc11","fgc12","fgc13","fgc14","fgc15","fgc16","fgc17","fgc18","fgc19","fgc20","fgc21","fgc22","fgc23","fgc24","fgc25","fgc26","fgc27","fgc28","fgc29","fgc30","fgc31","fgc32","fgc33","fgc34","fgc35","fgc36","fgc37","fgc38","fgcspare1","fgcspare2","fgcspare3","fgcspare4"]
tests = ["Network", "GPU", "Time", "Gidel", "Snapshot", "Disks"]
testbuttons = []
serverbuttons = []
managebuttons = []
fgcbuttons = []
class mainwindow:
global test
global testbuttons
global managment
global managebuttons
global FGCs
def __init__(self,master):
self.master = master
master.title("System Report Tool")
master.geometry("1000x500")
self.Tests = ttk.LabelFrame(root, text="Tests")
self.Tests.pack(expand="no", anchor=W, pady=20)
for test in tests:
testcheck = ttk.Checkbutton(self.Tests, text=test)
testcheck.pack(side=LEFT, anchor="n")
testbuttons.append(testcheck)
def select_tests():
for test in testbuttons:
test.invoke()
selecttests = ttk.Checkbutton(root, text="Select All",command=select_tests)
selecttests.place(x=260,y=16)
self.Managment = ttk.LabelFrame(root, text="Managment")
self.Managment.configure(width=10, height=20)
self.Managment.pack(expand="no",anchor=W)
for manage in managment:
managecheck = ttk.Checkbutton(self.Managment, text=manage)
managecheck.pack(side=TOP, anchor="w")
managebuttons.append(managecheck)
def select_manage():
for manage in managebuttons:
manage.invoke()
selectmanage = ttk.Checkbutton(self.Managment, text="Select All",command=select_manage)
selectmanage.pack()
self.FGCs = ttk.LabelFrame(root, text="FGCs")
self.FGCs.configure(width=10, height=20)
self.FGCs.place(x=120, y=80)
self.sf = ScrolledFrame(self.FGCs)
self.sf.pack()
for fgc in FGCs:
fgccheck = ttk.Checkbutton(self.sf.inner, text=fgc)
fgccheck.pack(side=TOP, anchor="w")
fgcbuttons.append(fgccheck)
def select_fgc():
for fgc in fgcbuttons:
fgc.invoke()
selectfgc = ttk.Checkbutton(self.sf.inner, text="Select All",command=select_fgc)
selectfgc.pack()
root = Tk()
Window = mainwindow(root)
root.mainloop()
EDIT: This code uses pack() with some options to resize widgets when window is resized
import os
import subprocess
import tkinter as tk
from tkinter import *
from tkinter import ttk
class ScrolledFrame(tk.Frame):
def __init__(self, parent, vertical=True, horizontal=False):
super().__init__(parent)
# canvas for inner frame
self._canvas = tk.Canvas(self)
self._canvas.grid(row=0, column=0, sticky='news') # changed
# create right scrollbar and connect to canvas Y
self._vertical_bar = tk.Scrollbar(self, orient='vertical', command=self._canvas.yview)
if vertical:
self._vertical_bar.grid(row=0, column=1, sticky='ns')
self._canvas.configure(yscrollcommand=self._vertical_bar.set)
# create bottom scrollbar and connect to canvas X
self._horizontal_bar = tk.Scrollbar(self, orient='horizontal', command=self._canvas.xview)
if horizontal:
self._horizontal_bar.grid(row=1, column=0, sticky='we')
self._canvas.configure(xscrollcommand=self._horizontal_bar.set)
# inner frame for widgets
self.inner = tk.Frame(self._canvas)
self._window = self._canvas.create_window((0, 0), window=self.inner, anchor='nw')
# autoresize inner frame
self.columnconfigure(0, weight=1) # changed
self.rowconfigure(0, weight=1) # changed
# resize when configure changed
self.inner.bind('<Configure>', self.resize)
# resize inner frame to canvas size
self.resize_width = False
self.resize_height = False
self._canvas.bind('<Configure>', self.inner_resize)
def resize(self, event=None):
self._canvas.configure(scrollregion=self._canvas.bbox('all'))
def inner_resize(self, event):
# resize inner frame to canvas size
if self.resize_width:
self._canvas.itemconfig(self._window, width=event.width)
if self.resize_height:
self._canvas.itemconfig(self._window, height=event.height)
managment = ["MAIN","NAV","OUTPUT","OUTPUTSPARE","GATEWAY","Sync1","Sync2"]
servers = ["recon01","recon02","recon03","recon04","recon05","recon06","recon07","recon08","recon09","recon10","recon11","recon12","render01","render02","storinator"]
FGCs =["fgc01","fgc02","fgc03","fgc04","fgc05","fgc06","fgc07","fgc08","fgc09","fgc10","fgc11","fgc12","fgc13","fgc14","fgc15","fgc16","fgc17","fgc18","fgc19","fgc20","fgc21","fgc22","fgc23","fgc24","fgc25","fgc26","fgc27","fgc28","fgc29","fgc30","fgc31","fgc32","fgc33","fgc34","fgc35","fgc36","fgc37","fgc38","fgcspare1","fgcspare2","fgcspare3","fgcspare4"]
tests = ["Network", "GPU", "Time", "Gidel", "Snapshot", "Disks"]
testbuttons = []
serverbuttons = []
managebuttons = []
fgcbuttons = []
class mainwindow:
global test
global testbuttons
global managment
global managebuttons
global FGCs
def __init__(self,master):
self.master = master
master.title("System Report Tool")
master.geometry("1000x500")
# --- top ---
self.Tests = ttk.LabelFrame(root, text="Tests")
self.Tests.pack(anchor='w', pady=20)
for test in tests:
testcheck = ttk.Checkbutton(self.Tests, text=test)
testcheck.pack(side='left', anchor="n")
testbuttons.append(testcheck)
def select_tests():
for test in testbuttons:
test.invoke()
selecttests = ttk.Checkbutton(root, text="Select All",command=select_tests)
selecttests.place(x=260,y=16)
# --- middle ---
self.Managment = ttk.LabelFrame(root, text="Managment")
self.Managment.configure(width=10, height=20)
self.Managment.pack(anchor='nw', side='left')
for manage in managment:
managecheck = ttk.Checkbutton(self.Managment, text=manage)
managecheck.pack(anchor="w")
managebuttons.append(managecheck)
def select_manage():
for manage in managebuttons:
manage.invoke()
selectmanage = ttk.Checkbutton(self.Managment, text="Select All",command=select_manage)
selectmanage.pack()
self.FGCs = ttk.LabelFrame(root, text="FGCs")
self.FGCs.configure(width=10, height=20)
self.FGCs.pack(fill='y', expand=True, side='left', anchor='w')
self.sf = ScrolledFrame(self.FGCs)
self.sf.pack(fill='y', expand=True)
for fgc in FGCs:
fgccheck = ttk.Checkbutton(self.sf.inner, text=fgc)
fgccheck.pack(anchor="w")
fgcbuttons.append(fgccheck)
def select_fgc():
for fgc in fgcbuttons:
fgc.invoke()
selectfgc = ttk.Checkbutton(self.sf.inner, text="Select All", command=select_fgc)
selectfgc.pack()
root = Tk()
Window = mainwindow(root)
root.mainloop()

Tkinter blank window

I found this introductory tutorial online, but when I run it, I get just a blank window. Any idea what's going wrong?
# A more complex example showing the use of classes in GUI programming
from tkinter import *
class GUIExample:
def __init__(self, master):
self.master = master # for showInfo()
# Create frame to hold widgets
frame = Frame(master)
# Create label for header
self.headLbl = Label(frame, text="Widget Demo Program", relief=RIDGE)
self.headLbl.pack(side=TOP, fill=X)
# Dummy frame for border
spacerFrame = Frame(frame, borderwidth=10)
# Create frame to hold center part of the form
centerFrame = Frame(spacerFrame)
leftColumn = Frame(centerFrame, relief=GROOVE, borderwidth=10)
rightColumn = Frame(centerFrame, relief=GROOVE, borderwidth=10)
# Some colorful widgets
self.colorLabel = Label(rightColumn, text="Select a color")
self.colorLabel.pack(expand=YES, fill=X)
entryText = StringVar(master)
entryText.set("Select a color")
self.colorEntry = Entry(rightColumn, textvariable=entryText)
self.colorEntry.pack(expand=YES, fill=X)
# Create some radio buttons
self.radioBtns = []
self.radioVal = StringVar(master)
btnList = ("black", "red", "green", "blue", "white", "yellow")
for color in btnList:
self.radioBtns.append(Radiobutton(leftColumn, text=color, value=color, \
indicatoron=TRUE, variable=self.radioVal, command=self.updateColor))
else:
if (len(btnList) > 0):
self.radioVal.set(btnList[0])
self.updateColor()
for btn in self.radioBtns:
btn.pack(anchor=W)
# Make the frames visible
leftColumn.pack(side=LEFT, expand=YES, fill=Y)
rightColumn.pack(side=LEFT, expand=YES, fill=BOTH)
centerFrame.pack(side=TOP, expand=YES, fill=BOTH)
# Create an indicator checkbutton
self.indicVal = BooleanVar(master)
self.indicVal.set(TRUE)
self.updateIndic()
Checkbutton(spacerFrame, text="Show indicator", command=self.updateIndic, \
variable=self.indicVal).pack(side=TOP, fill=X)
# Create the Info button
Button(spacerFrame, text="Info", command=self.showInfo).pack(side=TOP, fill=X)
# Create the Quit button
Button(spacerFrame, text="Quit", command=self.quit).pack(side=TOP, fill=X)
def quit(self):
import sys
sys.exit()
def updateColor(self):
self.colorLabel.configure(fg=self.radioVal.get())
self.colorEntry.configure(fg=self.radioVal.get())
def updateIndic(self):
for btn in self.radioBtns:
btn.configure(indicatoron=self.indicVal.get())
def updateColorPrev(self):
if (self.colorprevVal.get()):
for btn in self.radioBtns:
color = btn.cget("text")
btn.configure(fg=color)
else:
for btn in self.radioBtns:
btn.configure(fg="black")
def showInfo(self):
toplevel = Toplevel(self.master, bg="white")
toplevel.transient = self.master
toplevel.title("Program info")
Label(toplevel, text="A simple Tkinter demo", fg="navy", bg="white").pack(pady=20)
Label(toplevel, text="Written by Bruno Dufour", bg = "white").pack()
Label(toplevel, text="http://www.cs.mcgill.ca/ Ėƒbdufou1/", bg="white").pack()
Button(toplevel, text="Close", command=toplevel.withdraw).pack(pady=30)
root = Tk()
ex = GUIExample(root)
root.title("A simple widget demo")
root.mainloop()
They forgot
frame.pack()
and
spacerFrame.pack()
I didn't test rest of code.
EDIT: BTW: In place of
def quit(self):
import sys
sys.exit()
I would use something more natural - and less drastic
def quit(self):
self.master.destroy()

create an image in the canvas using a button event tkinter

I need to add an event to my buttons in a Tkinter gui that will create an image in the canvas. How do I do it?
Thanks All
It works but I need to get a dynamic number images of the same image file, but everytime I create a new image the old image gets garbage collected. I cant think of what to do. I want to have multiple instances of the same image on my canvas. Please, would be glad for some suggestions
my code
from Tkinter import *
import tkMessageBox
def callback():
if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"):
root.destroy()
class AppUI(Frame):
def __init__(self, master):
Frame.__init__(self, master, background="white", relief=FLAT, bd=2, height=768, width=1024)
self.menubar = Menu(self)
menu = Menu(self.menubar)
self.menubar.add_cascade(label="File", menu=menu)
menu.add_command(label="New")
menu.add_command(label="Open")
menu.add_command(label="Save As")
menu.add_command(label="Save Copy of")
menu.add_separator()
menu.add_command(label="exit")
menu = Menu(self.menubar)
self.menubar.add_cascade(label="Edit", menu=menu)
menu.add_command(label="Cut")
menu.add_command(label="Copy")
menu.add_command(label="Paste")
menu = Menu(self.menubar)
self.menubar.add_cascade(label="Debug", menu=menu)
menu.add_command(label="Open Debugger")
menu.add_command(label="Auto-debug")
menu.add_command(label="Revert")
menu = Menu(self.menubar)
self.menubar.add_cascade(label="Run", menu=menu)
menu.add_command(label="Stimulation")
menu.add_command(label="Check")
menu.add_command(label="Scan Module")
menu = Menu(self.menubar)
self.menubar.add_cascade(label="Help", menu=menu)
menu.add_command(label="Help files")
menu.add_command(label="FTA site")
menu.add_separator()
menu.add_command(label="Credits")
self.master.config(menu=self.menubar)
f0 = Frame(root, background="white")
b1 = Button(f0, bd=2, padx=15, pady=15, justify = LEFT)
photo1 = PhotoImage(file="Images/p1.gif")
b1.config(image = photo1,width="50",height="50", command=self.create_image1)
b1.image = photo1
b1.pack(side=LEFT)
b2 = Button(f0, bd=2, padx=15, pady=15, justify = LEFT)
photo2 = PhotoImage(file="Images/p4.gif")
b2.config(image=photo2, width="50",height="50", command = self.create_image2)
b2.image = photo2
b2.pack(side=LEFT)
b3 = Button(f0,padx=15, bd=2, pady=15, justify = LEFT)
photo3 = PhotoImage(file="Images/p8.gif")
b3.config(image=photo3, width="50",height="50", command = self.create_image3)
b3.image = photo3
b3.pack(side=LEFT)
b4 = Button(f0,padx=15, bd=2, pady=15, justify = LEFT)
photo4 = PhotoImage(file="Images/p7.gif")
b4.config(image=photo4, width="50",height="50", command = self.create_image4)
b4.image = photo4
b4.pack(side=LEFT)
b5 = Button(f0,padx=15, bd=2, pady=15, justify = LEFT)
photo5 = PhotoImage(file="Images/p5.gif")
b5.config(image=photo5, width="50",height="50", command=self.create_image5)
b5.image = photo5
b5.pack(side=LEFT)
f0.pack(anchor=NW, side=TOP)
self.canvas = Canvas(self, height=750, width=1500, bg="white")
self.canvas.pack(side=LEFT)
def create_image1(self):
photos1 = PhotoImage(file="Images/p1.gif")
self.photos1=photos1
self.img1=self.canvas.create_image(60, 60, image=photos1)
self.canvas.bind("<B1-Motion>", self.move_image1)
def create_image2(self):
photos2 = PhotoImage(file="Images/p4.gif")
self.photos2=photos2
self.img2=self.canvas.create_image(60, 60, image=photos2)
self.canvas.bind("<B1-Motion>", self.move_image2)
def create_image3(self):
photos3 = PhotoImage(file="Images/p8.gif")
self.photos3=photos3
self.img3=self.canvas.create_image(60, 60, image=photos3)
self.canvas.bind("<B1-Motion>", self.move_image3)
def create_image4(self):
photos4 = PhotoImage(file="Images/p7.gif")
self.photos4=photos4
self.img4=self.canvas.create_image(60, 60, image=photos4)
self.canvas.bind("<B1-Motion>", self.move_image4)
def create_image5(self):
photos5 = PhotoImage(file="Images/p5.gif")
self.photos5=photos5
self.img5=self.canvas.create_image(60, 60, image=photos5)
self.canvas.bind("<B1-Motion>", self.move_image5)
def move_image1(self, event):
self.canvas.delete(self.img1)
x = event.x
y = event.y
self.img1 = self.canvas.create_image(x, y, image=self.photos1, anchor='nw')
self.canvas.update()
def move_image2(self, event):
self.canvas.delete(self.img2)
x = event.x
y = event.y
self.img2 = self.canvas.create_image(x, y, image=self.photos2, anchor='nw')
self.canvas.update()
def move_image3(self, event):
self.canvas.delete(self.img3)
x = event.x
y = event.y
self.img3 = self.canvas.create_image(x, y, image=self.photos3, anchor='nw')
self.canvas.update()
def move_image4(self, event):
self.canvas.delete(self.img4)
x = event.x
y = event.y
self.img4 = self.canvas.create_image(x, y, image=self.photos4, anchor='nw')
self.canvas.update()
def move_image5(self, event):
self.canvas.delete(self.img5)
x = event.x
y = event.y
self.img5 = self.canvas.create_image(x, y, image=self.photos5, anchor='nw')
self.canvas.update()
root = Tk()
root.protocol("WM_DELETE_WINDOW", callback)
app = AppUI(root)
app.pack()
root.mainloop()
Also, only the last drawn image can be dragged and dropped All previous images cannot be interacted with. And, as I said, I cant seem to create multiple clone images. I know that I should anchor all the images so that they don't get garbage collected but I cant seem to find out a way to do that. I tried return the image instance of the function create_image to an array. but it didn't work. Thanks in advance
What problem are you specifically having? There's nothing tricky about it:
def __init__(...):
...
self.canvas = tk.Canvas(...)
b = tk.Button(..., command=self.create_image)
...
def create_image(self):
self.canvas.create_image(...)
The important thing to remember is that the images will get garbage-collected unless you keep a reference to them. Since you are creating multiple images, an easy way to do this is to create a list to which you can append references to the images:
def __init__(...):
...
self.images = []
...
photo1 = PhotoImage(file="Images/p1.gif")
self.images.append(photo1)
...
There are some other problems with your code. For one, you don't need to delete and then recreate the images when they are moved. The canvas has a move method specifically for moving existing items. Also, the calls to self.canvas.update() are completely useless.
Finally, your code will be considerably easier to maintain if you only have a single "move" method, rather than one for each image. That's off topic for this specific question, but you might want to search for lambda and functools.partial as solutions for being able to pass arguments via bindings.

Categories