【问题标题】:organising frames组织框架
【发布时间】: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

我真的很喜欢第二个版本,直到我看到板完全消失的结果。任何指针将不胜感激。

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

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

    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)

    框架的布局是这样的:

    【讨论】:

    • 谢谢你,这几乎是完美的。它在底部留下了一些空白空间(在我再次询问之前,我将尝试修复它!)。但是有一个后续:sticky='new' 或 sticky='nsw' 是什么意思?
    • @Andrew sticky= 基本上告诉小部件如果单元格变得比小部件大,它们应该粘贴到单元格的哪一侧,默认是将小部件在单元格中居中。 NSEW 分别代表北、南、东、西,所以上、下、右和左。 NSEW 是 tkinter 常量,定义为 'n''s''e''w',所以当你希望小部件粘在顶部时,底部和左侧您可以使用sticky=N+S+Wsticky='nsw'。阅读更多effbot
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    相关资源
    最近更新 更多