使用Python和Tkinter

时间:2015-09-13 20:11:05

标签: python tkinter

我用Python写了一个简单的游戏。现在我试图给它一个GUI(目前它是基于文本的)。由于没有移动物体,我决定使用Tkinter(我喜欢网格排列,东部编码以获得菜单以及不需要安装任何东西的事实)。

我有一些似乎无法解决的问题:

  1. 我想在屏幕上显示两个游戏板。我创建了一个包含信息的框架类并显示它,但它只显示第一个。第二个已创建但未出现在屏幕上。

  2. 主板上的所有磁贴都具有相同的功能,但是当我按下磁贴(标签对象)时,我想使用该对象的一些元数据。也就是说,我想给它分配一个字符串,当我按下它时,我希望将字符串附加到我按下的标签上。我无法弄清楚该怎么做。 ---在Eric Levieil的评论中解决

  3. (最不重要)我可以放两张图片,一张不用帆布/绝对位置吗?

  4. 这是我的代码:

    import tkinter as tk
    from tkinter import ttk
    
    class GameBoard(ttk.Frame):
        tiles = []
        def __init__(self, parent, temp, *args, **kwargs):
            ttk.Frame.__init__(self, parent)
            self.parent = parent
            self.graphics = {'1H':tk.PhotoImage(file='graphics/1H.gif'),
                    '0': tk.PhotoImage(file='graphics/0.gif')}
    
            for row_num in range(5):
                row = []
                for cell_num in range(10):
                    row.append(ttk.Label(self))
                    row[cell_num]['image'] = self.graphics[temp]
                    row[cell_num].bind('<Button-1>', lambda event: print('(%d,%d)'%(row_num,cell_num)))
                self.tiles.append(row)
    
            for row_num in range(5):
                for cell_num in range(10):
                    self.tiles[row_num][cell_num].grid(row=row_num, column=cell_num)
    
    
    class MainBoard(ttk.Frame):
        def __init__(self, parent, *args, **kwargs):
            ttk.Frame.__init__(self, parent)
            player_1_name = ttk.Label(self, text='Player 1').grid(row=0, sticky=tk.W)
            player_1_board = GameBoard(self, '0')
            player_1_board.grid(row=1, sticky=(tk.N, tk.W))       
            player_2_name = ttk.Label(self, text='Player 2').grid(row=2, sticky=tk.W)
            player_2_board = GameBoard(self, '1H')
            player_2_board.grid(row=3, sticky=(tk.S, tk.W))
            self.grid(row=0)
    
    
    
    def main():
        root = tk.Tk()
        root.title('Battleship')
        MainBoard(root)
        root.mainloop()
    
    if __name__ == '__main__':
        main()
    

    谢谢, URI

    编辑:以下是我正在使用的两张图片graphics.zip

1 个答案:

答案 0 :(得分:0)

问题的根源在于您如何定义tiles。由于您正在初始化它超出__init__,因此在此类的所有实例之间共享相同的tiles。如果您创建两个实例并在第二个实例中修改变量,它将影响第一个实例(反之亦然)

由于您希望每个实例都有自己的切片列表,因此您应该在__init__内初始化它:

class GameBoard(ttk.Frame):
    def __init__(self, parent, temp, *args, **kwargs):
        ttk.Frame.__init__(self, parent)
        self.parent = parent
        self.tiles = []
        ...

至于为按钮赋值的问题,你可以使用lambda或``functools.partial`,你需要创建一个闭包,这样的值绑定到每个实例:

row[cell_num].bind('<Button-1>', lambda event, row=row_num, cell=cell_num: print('(%d,%d)'%(row,cell)))

关于是否可以将图像叠加在一起的第三个问题有点模糊。这实际上取决于你想要的效果。您当然可以使用grid将两个图像放在同一个网格单元格中,或者使用place放在彼此的顶部。这是否给你你想要的视觉效果,我不知道。