为什么这些子类创建新的 tkinter 画布?

Why do these subclasses create new tkinter canvases?

我能够用更小的 50 行代码重现问题。这就是为什么您可能会看到看似 'useless' 需要参数和参数。

程序首先要做的是创建一个主 window 和游戏板对象,它是 tk.Canvas 的子class。该对象然后为每个 120x120 正方形创建 8 行和列,颜色交替。

然后,我创建游戏块(通常在 for 循环中完成,但这个 运行-down 示例只创建两个块)分别为它们提供 60x60 和 60x120 的位置。

最后,我用一个简单的退出按钮和 mainloop 功能将其包装起来。


我的代码似乎导致每次我尝试在板上放置一个图像项目时,在 GameBoard 上绘制一个新的 canvas。

现在,我 相信 这个错误源于 GameBoard class,特别是它调用 __init__ 基础方法 class.

我已经尝试在所有不同的地方工作和修改以放置每个 self 方法,认为这可能会有所帮助,但无济于事。

但是,如果我注释掉创建 rook 和 pawn 的两行,则棋盘显示正常。所以我知道肯定是碎片直接造成的

所以,这是我对国际象棋游戏的尝试。请记住,它还远未完成,下面的代码不是我的代码的摘录,而是为了显示错误而完全重新制作的代码。

如果您看到任何与我的实际问题无关的明显问题,请知道我正在尽最大努力避免重复自己,并遵循 pip8 指南.因此,我们将不胜感激任何关于清洁度或整体功能的意见。


正如 quamrana 在评论中指出的那样:我从 GameBoard 继承 GamePiece 的原因是 特别是 因为我想 而不是 必须担心更改图像的背景以匹配所述图像所在 space 的颜色。

import tkinter as tk
from PIL import ImageTk, Image

class GameBoard(tk.Canvas):
    def __init__(self, parent):
        self.color = ""

#where I believe my error comes from
        tk.Canvas.__init__(self, parent, height=960, width=960)
        self.grid()

#spaces created here by rows snd columns
    def create_spaces(self):
        x1, y1, x2, y2 = 0, -120, 120, 0
        for _row in range(8):
            x1, x2 = 0, 120
            y1 += 120
            y2 += 120
            self.alternate_colors()
            for _column in range(8):
                self.create_rectangle(x1, y1, x2, y2, fill=self.color)
                x1 += 120
                x2 += 120
                self.alternate_colors()

#each space created alternates between the two colors here
    def alternate_colors(self):
        if self.color == "green": self.color = "pink"
        else: self.color = "green"

class GamePiece(GameBoard):
    def __init__(self, parent, xPOS, yPOS, photo_file):
        GameBoard.__init__(self, parent)
        self.photo1 = Image.open(photo_file)
        self.photo2 = ImageTk.PhotoImage(self.photo1)
        self.create_image(xPOS, yPOS, image=self.photo2)
        self.grid()

#main window and gameboard is created here
window = tk.Tk()
gameboard = GameBoard(window)
gameboard.create_spaces()

#all pieces will eventually be created here using for loops
gamepiece1 = GamePiece(gameboard, 60, 60, "black_rook.png")
gamepiece2 = GamePiece(gameboard, 60, 120, "black_pawn.png")

#quit button and mainloop
tk.Button(window, text="Quit", command=quit, bd=5).grid(pady=40)
window.mainloop()

继承意味着子class 超class。如果您的 GamePiece 继承自 GameBoard,则 GamePiece 是一个 GameBoard。由于 GameBoard 创建了 canvas,GamePiece 也创建了

您似乎在使用继承来尝试在对象之间共享数据。这不是继承的目的。您的 GamePiece class 不应继承自 GameBoard

您在创建 GamePiece 时正确地将 GameBoard 的实例作为第一个参数传递,因此您的 GamePiece 应该在棋盘上绘制自己时使用它。它应该看起来像这样:

class GamePiece():
    def __init__(self, gameboard, xPOS, yPOS, photo_file):
        self.gameboard = gameboard
        self.photo1 = Image.open(photo_file)
        self.photo2 = ImageTk.PhotoImage(self.photo1)
        self.gameboard.create_image(xPOS, yPOS, image=self.photo2)