I am trying to make the GUI for a logic circuit simulator. My idea is that when the picture/icon for a gate is clicked, the object that picture/icon belongs to becomes selected and saved to be used for a later function that links two different gates together. However, the issue lies in that there seems to be no way to bind a mouse event to a picture in tkinter the same way you would with a button.
When running the program, an attribute error is thrown from the line
self.root.orIcon.tag_bind(orGateObject.getIcon(), '<Button-1>', lambda: self.makeSelected(orGateObject.getIcon()))
AttributeError: 'PhotoImage' object has no attribute 'tag_bind'
The same error is thrown when using .bind instead of .tag_bind as well.
from tkinter import *
class orGate:
def __init__(self):
self.filePath = 'Project programs/gate pictures/or.png'
self.icon = None
def getFilePath(self):
return self.filePath
def makeIconBelongTo(self, icon):
self.icon = icon
def getIcon(self):
return self.icon
class Window:
def __init__(self):
self.root = Tk() # root widget (window)
self.root.title("Logic Circuit Simulator")
# tool section
self.toolFrame = LabelFrame(self.root, text="Tools", width=100, height=500)
self.toolFrame.config(bg="lightgrey")
self.toolFrame.grid(row=0, column=0, padx=5, pady=5)
#gates section within tool section
self.gatesLabelFrame = LabelFrame(self.toolFrame, text="Gates", width=5, height=1, borderwidth=1, relief="ridge")
self.gatesLabelFrame.grid(row=0, column=0, padx=5, pady=10)
# workFrame
self.workFrame = Frame(self.root, width=1000, height=550)
self.workFrame.grid(row=0, column=1, padx=5, pady=5)
#actual visual frame (the circuit goes in here) within workFrame
self.visualFrame = LabelFrame(self.workFrame, text="Workspace", width=1000, height=500)
self.visualFrame.config(bg="lightgrey")
self.visualFrame.grid(row=1, column=0, padx=5, pady=5)
#options bar frame
self.optionsLabelFrame = LabelFrame(self.workFrame, text="Options", width= 1000, height=30)
self.optionsLabelFrame.config(bg="lightgrey")
self.optionsLabelFrame.grid(row=0, column=0, padx=5, pady=5)
#canvas (workspace) within visual frame
self.workspace = Canvas(self.visualFrame, bg="lightgrey", width=1000, height=500)
self.workspace.grid(row=0, column=0, padx=5, pady=5)
#buttons
orButton = Button(self.gatesLabelFrame, text="OR", command=lambda:self.createOrGate(), relief="groove")
orButton.grid(row=2, column=0, padx=5, pady=5)
self.gatesAndIcons = []
self.selectedObject = None
def runWindow(self):
return self.root.mainloop()
def makeSelected(self, icon):
for i in self.gatesAndIcons:
if i[1] == icon:
self.selectedObject = i[0]
print("selection made") # check if selection was made
def createOrGate(self):
#instantiate OR gate
orGateObject = orGate()
orIcon = PhotoImage(file=orGateObject.getFilePath())
self.root.orIcon = orIcon # to prevent the image garbage collected.
orGateObject.makeIconBelongTo(self.root.orIcon) # making the icon an attribute of the or gate object
self.workspace.create_image(500, 250, image=orGateObject.getIcon())
self.gatesAndIcons.append([orGateObject, orGateObject.getIcon()]) # create object and icon pair so when icon is clicked on the canvas, the object it belongs to becomes the selected item
self.root.orIcon.tag_bind(orGateObject.getIcon(), '<Button-1>', lambda: self.makeSelected(orGateObject.getIcon())) # the issue here is the binding of the click event to the icon
print(self.selectedObject)
Window = Window()
Window.runWindow()