【发布时间】:2019-01-18 00:43:32
【问题描述】:
我认为我对 tkinter 有一些基本的了解,但阅读了大量教程和其他答案后,我仍然不明白。我正在尝试组织一个简单的 GUI。它应该有一个带有活动按钮的游戏板(游戏是 othello)的左侧窗格(我已经省略了操作功能,因为它可以正常工作),然后是一个具有 3 个窗格的右侧窗格,从上到下:一个带有单选按钮以在 1 或 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 行被分开,两个文本行各自排成一行,而不是与游戏板的一行相对.
看到这不起作用,我读到一些关于网格不保留父框架和子框架之间的列和行的问题,所以我尝试了一种不同的方法,其中父框架分成 2 列,然后是子框架框架位于其下方,具有自己的行/列定义。但这也不起作用:
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
我真的很喜欢第二个版本,直到我看到板完全消失的结果。任何指针将不胜感激。
【问题讨论】: