组织框架

时间:2018-08-10 11:47:22

标签: python tkinter

我认为关于tkinter我不了解一些基本知识,但是阅读了大量教程和其他答案后,我仍然不明白。我正在尝试组织一个简单的GUI。它应该有一个带有游戏板的左侧窗格(游戏是othello),该板上具有活动按钮(我已经省略了动作功能,可以正常工作),然后是一个右侧窗格,其中包含3个窗格,从上到下:一个带有单选按钮,可在1个或2个玩家之间切换,一个带有当前得分,另一个带有游戏评估。就目前而言,后2个只是文本行。

我想我可以在父框架中设置一个网格结构,然后在该网格中具有4个框架,然后在其中构建小部件。这是代码(除非您想运行它,否则可以忽略Board类:我苦苦挣扎的那一点在Master中)

from tkinter import *
from collections import defaultdict
from PIL import Image as PIL_Image, ImageTk

class Master:
    def __init__(self):
        self.board = Board()
        self.display = Tk()
        self.f = Frame(self.display, width=1050, height=700)
        self.f.grid(row=0, column=0, rowspan=8, columnspan=8)
        self.frame2 = Frame(self.f)
        self.frame2.grid(row=0, column=8, rowspan=4, columnspan=4)
        self.frame3 = Frame(self.f)
        self.frame3.grid(row=4, column=8, rowspan=2, columnspan=4)
        self.frame4 = Frame(self.f)
        self.frame4.grid(row=6, column=8, rowspan=2, columnspan=4)
        self.text1 = Text(self.frame3)
        self.text1.pack()
        self.text2 = Text(self.frame4)
        self.text2.pack()
        self.square = defaultdict(Button)
        self.images = [ImageTk.PhotoImage(PIL_Image.open(f)) for f in ['white.png', 'empty.png', 'black.png']]
        modes = [('{} vs {}'.format(i,j), (i, j)) for i in ['human','computer'] 
        for j in ['human', 'computer']]
            v = StringVar()
            v.set(modes[0][1])
        for text, mode in modes:
            b = Radiobutton(self.frame2, text=text, variable=v, value=mode, command=lambda mode=mode: self.cp_set(mode))
            b.pack(anchor=W)
        self.text1.insert(END, 'score')
        self.text2.insert(END, 'evaluation')
        self.draw_board()
        self.display.mainloop()

    def draw_board(self):
        for i, j in [(x,y) for x in range(8) for y in range(8)]:
            self.square[i,j] = Button(self.f, command=lambda i=i, j=j: self.press(i,j), image=self.images[1 + self.board.square[i,j]])
            self.square[i,j].image = 1 + self.board.square[i,j]
            self.square[i,j].grid(column=i, row=j)

    def cp_set(self, m):
        self.pb, self.pw = m
        return

    def press(self, a, b):
        # make it do something
        return
class Board:
    def __init__(self, parent=None):
        self.parent = parent
        if parent:
            self.square = parent.square.copy()
            self.black_next = not parent.black_next
            self.game_over = parent.game_over
        else:
            self.square = defaultdict(int)
            for square in [(x,y) for x in range(8) for y in range(8)]:
                self.square[square] = 0
            for square in [(3,3), (4,4)]:
                self.square[square] = 1
            for square in [(3,4), (4,3)]:
                self.square[square] = -1
            self.black_next = True
            self.game_over = False

这给出了一张图片,其中游戏板的顶部4行与单选按钮对齐,但底部4行被拆分,两条文本行均排成一行,而不是在游戏板的对面

看到这行不通,我读到一些有关网格不保留父框架和子框架之间的行和列的问题,因此我尝试了另一种方法,将父框架分为两列,然后将子框架框架位于其下方,具有自己的行/列定义。但这也不起作用:

self.board = Board()
self.display = Tk()
self.f = Frame(self.display, width=1050, height=700)
self.f.grid(row=0, column=0, rowspan=1, columnspan=2)
self.frame1 = Frame(self.f, width=700, height=700)
self.frame1.grid(row=0, column=0, rowspan=8, columnspan=8)
self.f2 = Frame(self.f)
self.f2.grid(row=0, column=1, rowspan=2, columnspan=1)
self.frame2 = Frame(self.f2, width=350, height=350)
self.frame2.grid(row=0, column=0)
self.frame3 = Frame(self.f2, width=350, height=350)
self.frame3.grid(row=1, column=0)
self.text1 = Text(self.frame2)
self.text1.pack()
self.text2 = Text(self.frame3)
self.text2.pack()

# in this version, Radiobuttons are children of self.frame2,
# and Buttons in draw_board() are children of self.frame1

在看到董事会完全消失的结果之前,我非常喜欢第二版。任何指针将不胜感激。

1 个答案:

答案 0 :(得分:3)

您可能想尝试这样的事情:



from tkinter import *
from collections import defaultdict
from PIL import Image as PIL_Image, ImageTk

class Master:
    def __init__(self):
        self.board = Board()
        self.display = Tk()

        self.left = Frame(self.display)
        self.left.grid(row=0, column=0, sticky="new")

        self.right = Frame(self.display)
        self.right.grid(row=0, column=1)

        self.right_top = Frame(self.right)
        self.right_top.grid(row=0, column=0, sticky="nsw")

        self.right_mid = Frame(self.right)
        self.right_mid.grid(row=1, column=0)

        self.right_bottom = Frame(self.right)
        self.right_bottom.grid(row=2, column=0)

        self.text1 = Text(self.right_mid)
        self.text1.pack()
        self.text2 = Text(self.right_bottom)
        self.text2.pack()
        self.square = defaultdict(Button)
        self.images = [ImageTk.PhotoImage(PIL_Image.open(f)) for f in ['white.png', 'empty.png', 'black.png']]
        modes = [('{} vs {}'.format(i,j), (i, j)) for i in ['human','computer'] for j in ['human', 'computer']]
        v = StringVar()
        v.set(modes[0][1])
        for text, mode in modes:
            b = Radiobutton(self.right_top, text=text, variable=v, value=mode, command=lambda mode=mode: self.cp_set(mode))
            b.pack(anchor=W)
        self.text1.insert(END, 'score')
        self.text2.insert(END, 'evaluation')
        self.draw_board()
        self.display.mainloop()

    def draw_board(self):
        for i, j in [(x,y) for x in range(8) for y in range(8)]:
            self.square[i,j] = Button(self.left, command=lambda i=i, j=j: self.press(i,j), image=self.images[1 + self.board.square[i,j]])
            self.square[i,j].image = 1 + self.board.square[i,j]
            self.square[i,j].grid(column=i, row=j)


框架的布局如下:

enter image description here