Как передать холст другому классу Python? - PullRequest
0 голосов
/ 06 октября 2018

Я хочу передать свой холст, который я сделал в одном классе, в другой.Я пытался использовать наследование, но оно все еще не работает.

Я также пытался использовать метод get и set для получения circuitCanvas из класса programGUI, но он все еще не работает.Я нашел '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()

1 Ответ

0 голосов
/ 06 октября 2018

Холст 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, поэтому его экземпляры do имеют атрибут circuitCanvas.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...