我想将我在一堂课上制作的画布传递给另一堂课。我尝试使用继承,但仍然无法正常工作。
我还尝试使用get和set方法从programGUI类获取circuitCanvas,但它仍然无法正常工作。我在这里找到了“ getattr”来使用句点来获取画布,但是我也无法使其正常工作。有什么建议么?
这是我到目前为止使用get / set方法获得的代码:
from tkinter import *
from tkinter import ttk
gate_id=0
input_id=0
output_id=0
class titleLabel(Label):
def __init__(self,master,**config):
super(titleLabel,self).__init__(master,**config)
self.config(bg="LIGHTGREY")
self.config(width=33)
self.config(font=("Courier",30))
self.config(anchor=CENTER)
class buttonLayout(Button):
def __init__(self,master,**config):
super(buttonLayout,self).__init__(master,**config)
self.config(font=("Courier",12))
self.config(bg="LIGHTGREY")
class programGUI(Frame):
def __init__(self,master):
super(programGUI,self).__init__(master)
self.grid()
self.menuFrame = Frame(self)
self.circuitFrame = Frame(self)
self.circuitCanvas = Canvas(self.circuitFrame,height=800,width=900,bg="LIGHTBLUE")
self.create_menu_widgets()
self.create_circuit_widgets(self.circuitCanvas)
self.menuFrame.grid()
Circuit(self.circuitFrame)
def create_menu_widgets(self):
lblWelcome=titleLabel(self.menuFrame,text="LOGIC GATE CIRCUIT PROGRAM")
lblWelcome.grid(row=0,column=0,pady=12,padx=50)
lblTitle = Label(self.menuFrame,text="Main Menu",font="Courier",width=60)
lbl1=Label(self.menuFrame,width=60,bg="LIGHTBLUE")
lbl1.grid(row=5,column=0)
btnCircuit = buttonLayout(self.menuFrame,text="Create Circuit",command=lambda:self.goToCircuitScreen())
lbl2=Label(self.menuFrame,width=60,bg="LIGHTBLUE")
lbl2.grid(row=7,column=0)
btnExit = buttonLayout(self.menuFrame,text="Exit",command=lambda:self.quitProgram())
lbl4=Label(self.menuFrame,width=60,bg="LIGHTBLUE")
lbl4.grid(row=11,column=0)
lblTitle.grid(row=4,column=0,pady=12,padx=50)
btnCircuit.grid(row=6,column=0)
btnExit.grid(row=14,column=0)
lbl5=Label(self.menuFrame,width=60,bg="LIGHTBLUE")
lbl5.grid(row=13,column=0)
lbl6=Label(self.menuFrame,width=60,bg="LIGHTBLUE")
lbl6.grid(row=15,column=0)
lbl7=Label(self.menuFrame,width=60,bg="LIGHTBLUE")
lbl7.grid(row=16,column=0)
circuitPic=PhotoImage(file="circuit1.gif")
circuitPicLabel=Label(self.menuFrame,image=circuitPic)
circuitPicLabel.photo=circuitPic
circuitPicLabel.grid(row=16,column=0,padx=50)
self.menuFrame.config(bg="LIGHTBLUE")
lblTitle.config(bg="white",fg="BLACK")
def create_circuit_widgets(self,circuitCanvas):
lblWelcome=titleLabel(self.circuitFrame,text="LOGIC GATE CIRCUIT")
lblWelcome.place(x=50,y=25)
backButton = buttonLayout(self.circuitFrame,text="BACK",command=lambda:self.goToMenu())
backButton.place(x=775,y=650)
self.circuitCanvas.grid()
def addOutput():
global output_id
output_id+=1
output_tag="output-%s"%output_id
tags=("output",output_tag)
self.circuitCanvas.create_rectangle(200,200,225,225,width=5,fill="WHITE",tag=tags)
self.circuitCanvas.tag_bind(output_tag, "<B1-Motion>", lambda event, tag=output_tag: moveInOutput(event, tag))
def addInput():
global input_id
input_id+=1
input_tag="input-%s"%input_id
tags=("input",input_tag)
print(tags)
self.circuitCanvas.create_oval(200,200,225,225,fill="WHITE",width=5,tag=tags)
self.circuitCanvas.tag_bind(input_tag, "<B1-Motion>", lambda event, tag=input_tag: moveInOutput(event, tag))
def moveInOutput(event, tag):
x=event.x
y=event.y
coords=self.circuitCanvas.coords(tag)
movex=x-coords[0]
movey=y-coords[1]
self.circuitCanvas.move(tag, movex, movey)
for item in self.circuitCanvas.find_all():
tags = self.circuitCanvas.gettags(item)
if tag in tags:
if 'input' in tags:
#current item is an input of the moved object
#Get the items coordinates
coords = self.circuitCanvas.coords(item)
#Find if we overlap with other objects
closest = self.circuitCanvas.find_overlapping(coords[0]-5,coords[1]-5,coords[2]+5,coords[3]+5)
for closest_item in closest:
closest_tags = self.circuitCanvas.gettags(closest_item)
if 'output' in closest_tags:
#If we overlap with another object, print connected and the appropriate tags
print("connected", closest_tags, "-", tag)
connected_coords = self.circuitCanvas.coords(closest_item)
snapx = coords[0] - connected_coords[0]
snapy = coords[1] - connected_coords[1]
self.circuitCanvas.move(tag, -snapx, -snapy)
self.circuitCanvas.create_rectangle(120,130,760,600,fill="WHITE",width=5)
addInputBtn=buttonLayout(self.circuitFrame,text="Input",command=lambda:addInput())
addInputBtn.place(x=25,y=200)
addOutputBtn=buttonLayout(self.circuitFrame,text="Output",command=lambda:addOutput())
addOutputBtn.place(x=20,y=400)
def goToCircuitScreen(self):
self.menuFrame.grid_remove()
self.circuitFrame.grid()
def goToMenu(self):
self.circuitFrame.grid_remove()
self.menuFrame.grid()
def quitProgram(self):
exit()
class Circuit(programGUI):
def __init__(self,circuitFrame):
super(programGUI,self).__init__(circuitFrame)
self.runBtn=buttonLayout(circuitFrame,activebackground="green",text="Run",command=lambda:validationCircuit(self))
self.runBtn.place(x=250,y=630)
self.var = StringVar(circuitFrame)
self.var.set('NOT')
self.choices = ['NOT','AND','OR','NAND','XOR','NOR','|','--']
self.option = OptionMenu(circuitFrame, self.var, *self.choices)
self.option.place(x=790,y=200)
self.addNodeBtn = buttonLayout(circuitFrame, text="Add Node", command=lambda:self.gateSelected())
self.addNodeBtn.place(x=780,y=400)
self.clearButton = buttonLayout(circuitFrame,text="Clear",command=lambda:self.clearScreen())
self.clearButton.place(x=420,y=630)
self.orGATE()
self.norGATE()
self.moveGate()
self.getCanvas(programGUI)
self.setCanvas(programGUI)
def getCanvas(self,programGUI):
getattr(programGUI,"self.circuitCanvas")
return self.circuitCanvas()
def setCanvas(self,circuitCanvas):
setattr(Circuit,"self.circuitCanvas")
def gateSelected(self):
sf = self.var.get()
if sf=='OR':
self.orGATE()
elif sf=='NOR':
self.norGATE()
def validationCircuit(self):
empty(gate_id)
validGates(gate_id)
validInOutputs(outputNum,inputNum)
def clearScreen(self):
global gate_id
circuitCanvas=self.circuitFrame
self.circuitCanvas.delete("orgate","norgate","output","input")
gate_id=0
outputNum=0
inputNum=0
return outputNum,inputNum
def norGATE(self):
global gate_id
gate_id+=1
gate_tag="norgate-%s"%gate_id
tags=("norgate",gate_tag)
inputs = ("norgate", gate_tag, "input")
outputs = ("norgate", gate_tag, "output")
self.circuitCanvas.create_oval(240,217,255,232,fill="black",tag=tags)
self.circuitCanvas.create_polygon(200,200,250,225,200,250,210,225,width=5,tag=tags)
self.circuitCanvas.create_line(245,225,280,225,width=5,tag=tags)
self.circuitCanvas.create_line(210,213,173,213,width=5,tag=tags)
self.circuitCanvas.create_line(210,238,173,238,width=5,tag=tags)
#End of output
self.circuitCanvas.create_line(280,225,285,225, width=5, fill="red", tags=outputs)
#End of inputs
self.circuitCanvas.create_line(173,213,168,213, width=5, fill="blue", tags=inputs)
self.circuitCanvas.create_line(173,238,168,238, width=5, fill="blue", tags=inputs)
self.circuitCanvas.tag_bind(gate_tag, "<B1-Motion>", lambda event, tag=gate_tag: moveGate(event, tag))
def orGATE(self):
global gate_id
gate_id+=1
gate_tag="orgate-%s"%gate_id
tags=("orgate",gate_tag)
inputs = ("orgate", gate_tag, "input")
outputs = ("orgate", gate_tag, "output")
self.circuitCanvas.create_polygon(200,200,250,225,200,250,210,225,width=5,tag=tags)
self.circuitCanvas.create_line(245,225,280,225,width=5,tag=tags)
self.circuitCanvas.create_line(210,213,173,213,width=5,tag=tags)
self.circuitCanvas.create_line(210,238,173,238,width=5,tag=tags)
#End of output
self.circuitCanvas.create_line(280,225,285,225, width=5, fill="red", tags=outputs)
#End of inputs
self.circuitCanvas.create_line(173,213,168,213, width=5, fill="blue", tags=inputs)
self.circuitCanvas.create_line(173,238,168,238, width=5, fill="blue", tags=inputs)
self.circuitCanvas.tag_bind(gate_tag, "<B1-Motion>", lambda event, tag=gate_tag: moveGate(event, tag))
def moveGate(self,event,tag):
x=event.x
y=event.y
coords=self.circuitCanvas.coords(tag)
movex=x-coords[0]
movey=y-coords[1]
self.circuitCanvas.move(tag, movex, movey)
for item in self.circuitCanvas.find_all():
tags = self.circuitCanvas.gettags(item)
if tag in tags:
if 'input' in tags:
#current item is an input of the moved object
#Get the items coordinates
coords = self.circuitCanvas.coords(item)
#Find if we overlap with other objects
closest = self.circuitCanvas.find_overlapping(coords[0]-5,coords[1]-5,coords[2]+5,coords[3]+5)
for closest_item in closest:
closest_tags = self.circuitCanvas.gettags(closest_item)
if 'output' in closest_tags:
#If we overlap with another object, print connected and the appropriate tags
print("connected", closest_tags, "-", tag)
connected_coords = self.circuitCanvas.coords(closest_item)
snapx = coords[0] - connected_coords[0]
snapy = coords[1] - connected_coords[1]
self.circuitCanvas.move(tag, -snapx, -snapy)
root = Tk()
root.title("Logic Gate Circuit Program")
root.geometry("900x695")
myGUI = programGUI(root)
root.mainloop()
答案 0 :(得分:0)
circuitCanvas
画布只是programGUI
类实例的属性。
碰巧的是,通过继承,并且由于您正在使用super
对其进行初始化,因此Circuit
实例也是programGUI
的实例。
结果,Circuit
的实例已经具有一个circuitCanvas
属性,因此在其中,您只需编写self.circuitCanvas
。
现在在您的getCanvas
和setCanvas
方法上说一句话(按照上面的答案,您不需要,但是它们仍然需要备注)。
您对getCanvas
的定义如下:
def getCanvas(self,programGUI):
getattr(programGUI,"self.circuitCanvas")
return self.circuitCanvas()
首先,对getattr
的调用是无用的,因为您不对其返回值做任何事情(当然,不包括所有副作用,但希望没有)。
但是无论如何,第二个参数是您要查找的属性的名称,因此它应该只是circuitCanvas
。
return语句有点困惑。
您的目标是获得circuitCanvas
成员,那么为什么还要费心编写方法呢?
如果您可以在函数中使用self.circuitCanvas
,那么您也可以在外面使用。
此外,您正在通过写circuitCanvas
来呼叫self.circuitCanvas()
。
希望circuitCanvas
是tkinter.Canvas
的实例,该实例不可调用。
所以这只会崩溃。
setCanvas
太奇怪了。
有一个不使用事件的参数,您在setattr
类上使用Circuit
,这只会向该类本身添加一个属性...
您只是使事情复杂化了。
如上所述,您的Circuit
类扩展了programGUI
,因此它的实例做具有该circuitCanvas
属性。