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:
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:
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
movemethod specifically for moving existing items. Also, the calls toself.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
lambdaandfunctools.partialas solutions for being able to pass arguments via bindings.