2016-05-02 10 views
0

Ich erstelle ein einfaches Fenster mit tkinter und starten Sie es als Thread, um das Hauptprogramm neben dem Fenster zu halten. Dies ist eine verkürzte Version davon:Python: Attribut Fehler beim Versuch, Thread besitzende Variable

import tkinter as tk 
import threading 

class mainWindow(threading.Thread): 
    def __init__(self, winWidth=500, winHeight=300): 
     threading.Thread.__init__(self) 
     self.winWidth = winWidth 
     self.winHeight = winHeight 

     # Save all drawn objects, to move or delete them later 
     self.bricks = [] 

     self.start()     #start thread 

    def run(self): 
     # parent object for all windows 
     self.master = tk.Tk() 
     self.master.protocol("WM_DELETE_WINDOW", self.callback) 
     self.show() 

    def callback(self): 
     self.master.quit() 

    # Initialize everything important 
    def show(self, tileSize=10): 
     # create main window 
     self.w = tk.Canvas(
       self.master, 
       width=self.winWidth, 
       height=self.winHeight, 
       background="white") 

     self.w.pack() 

     # draw brick 
     color = "gray49" 
     posX = 200 
     posY = 100 
     self.bricks.append(self.w.create_rectangle(posX, posY, posX+20, posY+20, fill=color)) 
     tk.mainloop() 

    def move_brick(self, x,y): 
     self.w.move(self.brick, x, y) 


mainWindow = mainWindow() 
mainWindow.move_brick(100,100) 

Wenn ich führen Sie den angezeigten Code das Fenster richtig öffnet, aber wenn ich versuche, das Rechteck zu bewegen mit move_brick(...) bekomme ich diesen Fehler:

AttributeError: 'mainWindow' object has no attribute 'w' 

Warum kann finde das Objekt meine Canvas w?

Antwort

1

Sie haben wahrscheinlich eine Race-Bedingung, die für Gewindeanwendungen üblich ist. Der Hauptthread ruft wahrscheinlich move_brick auf, bevor der Worker-Thread eine Chance hat, das Widget zu erstellen.

Sie können dies wahrscheinlich beobachten, wenn Sie direkt vor und nach dem Erstellen des Widgets und in Ihrer move_brick Funktion Druckanweisungen hinzufügen.

Auch wenn Sie dies beheben, wird dieser Code wahrscheinlich nicht funktionieren, da der gesamte tkinter-Code in einem einzigen Thread ausgeführt werden muss. Das Erstellen der GUI in einem Thread und das Aufrufen von move_brick in einem anderen Thread ist nicht der richtige Weg, um tkinter zu verwenden.

+0

Ich bin neu in tkinter und benutze es nur, um einige Prozesse zu debuggen. Wie kann ich die GUI von meinem Hauptprogramm aus ändern? – Jonas

+0

Ich überprüft mit den print-Anweisungen, wenn ich 'move_brick()' spät genug nach der Initialisierung des Fensters aufrufen, funktioniert es gut. – Jonas

+0

@Jonas: re _ "Wie könnte ich erreichen, um die GUI zu ändern" _ hängt davon ab, was Sie wirklich versuchen zu tun. Wenn du nur ein paar hundert Steine ​​um dich herum bewegst, brauchst du keine Fäden. Tkinter hat eine Methode ('after'), mit der Dinge periodisch ausgeführt werden können, z. B. Objekte auf dem Bildschirm verschieben. –

Verwandte Themen