Tkinter - 单击按钮时在 类 之间传递按钮网格值

Tkinter - pass button grid values between classes upon clicking button

我正在尝试使用 Tkinter 在 Python 中创建一个基本的战舰游戏。

下面是我的代码的一个非常简化的版本。本质上,我正在创建一个 10*10 的按钮网格并使用 .grid 定位它们。我想要做的是单击其中一个按钮并将该按钮的网格值 (x, y) 从 GameBoard class 传递到 Battleship class 以定位船.

我曾尝试使用 self.row = rowself.column = column,但是当我这样做时,我立即收到属性错误,'GameBoard' object has no attribute 'row'

import tkinter as tk

class GameBoard:
    def __init__(self):
        self.mw = tk.Tk()
        self.size = 10

    def build_grid(self):
        for x in range(self.size):
            for y in range(self.size):
                self.button = tk.Button(self.mw, text = '', width = 2, height = 1,\
                command = lambda row = x, column = y: self.clicked(row, column))
                self.button.grid(row = x, column = y)
            
    def clicked(self, row, column):
        print(row, column)
        self.row = row
        self.column = column

class Battleship:
    def __init__(self, board):
        self.gboard = board

    def position_ship(self):
        x = self.gboard.row
        y = self.gboard.column
        for i in range (3):
            self.submarine = tk.Button(self.gboard.mw, background = "black", text = '',\
                                   width = 2, height = 1)
            self.submarine.grid(row = x, column = y)
              
def main():
    gboard = GameBoard()
    gboard.build_grid()
    bt = Battleship(gboard)
    bt.position_ship()    
main()

正如@acw1668 在评论中指出的那样,问题是当您在main() 函数。

我不知道你的整体游戏设计,但解决这个问题的一个非常简单的方法是在 GameBoard.__init__() 方法中为他们分配一个随机的棋盘位置。

我还修改了代码以显示如何在单击按钮时调用 bt.position_ship()。这是通过将 BattleShip 实例 bt 传递给 build_grid() 函数来完成的,因此它可以包含在对 clicked() 方法的调用中,该方法现在可以在调用时调用它。

from random import randrange
import tkinter as tk

class GameBoard:
    def __init__(self):
        self.mw = tk.Tk()
        self.size = 10
        self.row = randrange(self.size)
        self.column = randrange(self.size)

    def build_grid(self, bt):
        for x in range(self.size):
            for y in range(self.size):
                self.button = tk.Button(self.mw, text='', width=2, height=1,
                                        command=lambda row=x, column=y:
                                            self.clicked(bt, row, column))
                self.button.grid(row=x, column=y)

    def clicked(self, bt, row, column):
        print(row, column)
        self.row = row
        self.column = column
        bt.position_ship()


class Battleship:
    def __init__(self, board):
        self.gboard = board

    def position_ship(self):
        x = self.gboard.row
        y = self.gboard.column
        for i in range (3):
            self.submarine = tk.Button(self.gboard.mw, background="black", text='',
                                       width=2, height=1)
            self.submarine.grid(row=x, column=y)


def main():
    gboard = GameBoard()
    bt = Battleship(gboard)
    gboard.build_grid(bt)
    bt.position_ship()
    tk.mainloop()

main()