无法访问类属性

时间:2015-11-20 20:02:13

标签: python-3.x tkinter

我试图加载应该在自己的线程中运行的Tkinter UI。创建UI实例后,尝试访问属性时出现此错误:line 18, in do_move: self.game_ui.setTile(4, 0, 0) AttributeError: 'Play' object has no attribute 'game_ui'

我不确定是否搞砸了线程或其他内容,但我也注意到self.game_ui.drawBoard(..)实际上并没有更新UI。

import GUI
import game


class Play:
    def __init__(self):
        print ('Init')
        self.game_core = game.Board()
        print(self.game_core.tiles)
        self.game_ui = GUI.getNewBoardWindow(self.keylistener)
        self.game_ui.drawBoard(self.game_core.tiles)

    def keylistener(self, event):
        self.do_move((event.keycode-38) % 4)

    def do_move(self, key):
        print(key)
        self.game_ui.setTile(4, 0, 0)


def main():
    Play()


main()

GUI是这样的:

from tkinter import *
from threading import Thread


class GUI(Frame, Thread):
    cellColors = {0: "#CCC0B3", 2: "#eee4da", 4: "#ede0c8", 8: "#f2b179", 16: "#f59563", 32: "#f67c5f", 64: "#f65e3b", 128: "#edcf72", 256: "#edcc61", 512: "#edc850", 1024: "#edc53f", 2048: "#edc22e", 4096: "#3c3a32"}
    boardSize = 4

    def __init__(self, parent):
        Frame.__init__(self, parent, bg="#BBADA0")
        Thread.__init__(self)
        self.parent = parent
        self.cells = []
        self.initUI(150)
        self.pack()
        self.start()
        self.parent.mainloop()

    def initUI(self, cellSize):
        for row in range(self.boardSize-1, -1, -1):
            self.cells.append([])
            for column in range(self.boardSize):
                cell = Frame(self, width=cellSize, height=cellSize)
                cell.grid(row=row, column=column, padx=4, pady=4)
                cell.pack_propagate(0)

                tile = Label(cell, bg="#CCC0B3", font=("Helvetica", 35, "bold"))
                tile.pack(fill=BOTH, expand=1)
                self.cells[-1].append(tile)

    def setTile(self, value, x, y):
        print(value)
        self.cells[y][x].config({
            "bg": GUI.cellColors[min(4096, value)],
            "fg": ("#776E65" if value < 8 else "#f9f6f2"),
            "text": str(value) if value else ''})

    def drawBoard(self, board):
        for col in range(len(board)):
            for row in range(len(board)):
                self.setTile(board[col][row], col, row)


def getNewBoardWindow(listener=None):
    root = Tk()
    root.title("2048")
    if listener:
        root.bind("<Key>", listener)

    app = GUI(root)
    root.mainloop()
    #mainThread = Thread(target=root.mainloop)
    #mainThread.start()
    return app

1 个答案:

答案 0 :(得分:1)

您启动root.mainloop()中的主循环getNewBoardWindow(),然后app会返回self.game_ui Play getNewBoardWindow() self.game_ui。由于root在GUI运行时无法返回,因此app不能存在。

您可以通过返回def getNewBoardWindow(listener=None): root = Tk() root.title("2048") if listener: root.bind("<Key>", listener) app = GUI(root) return app, root Play

来解决此问题
class Play:
    def __init__(self):
        print ('Init')
        self.game_core = game.Board()
        print(self.game_core.tiles)
        self.game_ui, self.root = GUI.getNewBoardWindow(self.keylistener)
        self.game_ui.drawBoard(self.game_core.tiles)
        self.root.mainloop()

root.mainloop()

__init__()

我建议您重新设计自己的程序,以便$sql ="SELECT id, first_name, last_name FROM actors"; $result = mysql_query($sql); while($row=mysql_fetch_array($result)) { if ($row['first_name'] == $firstname && $row['last_name'] == $lastname) { $actorID = $row['id']; echo "$actorID<br>"; } }//end while $sql2 = "SELECT actor_id, movie_id, role FROM roles"; $result2 = mysql_query($sql2); while ($row=mysql_fetch_array($result2)) { if ($row['actor_id'] == $actorID) { $movieID = $row['movie_id']; $actRole = $row['role']; echo "$movieID <br>"; echo "$actRole <br>"; } } //end while $sql3 = "SELECT id, name, year FROM movies"; $result3 = mysql_query($sql3); while ($row=mysql_fetch_array($result3)) { if ($row['id'] == $movieID) { $movieName = $row['name']; $movieYear = $row['year']; echo "$movieName <br>"; echo "$movieYear <br>"; } } //end while echo ' <table> <thead> <tr> <th> Movie Name </th> <th> Actor Role </th> <th> Release Date </th> </tr> </thead> <tbody> <td>'. $movieName .'</td> <td>'. $actRole. '</td> <td>'. $movieYear. '</td> </tbody> </table>'; ?> 位于主程序的末尾,而不是{{1}}内。