Python:尝试访问线程拥有的变量时出现属性错误

时间:2016-05-02 13:15:55

标签: multithreading python-3.x tkinter tkinter-canvas

我创建了一个带有tkinter的简单窗口,并将其作为线程启动,以使主程序在窗口旁边运行。这是它的缩短版本:

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)

当我运行显示的代码时,窗口会正确打开,但当我尝试使用move_brick(...)移动矩形时,我收到此错误:

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

为什么对象找不到我的Canvas w

1 个答案:

答案 0 :(得分:1)

您可能遇到竞争条件,这对于线程应用程序很常见。主线程可能在工作线程有机会创建窗口小部件之前调用move_brick

如果您在创建窗口小部件之前和之后以及move_brick函数中添加了打印语句,则可能会发生这种情况。

即使您解决了这个问题,这段代码也可能无法正常工作,因为所有tkinter代码都需要在单个线程中运行。在一个线程中创建GUI并在另一个线程中调用move_brick不是使用tkinter的正确方法。