【问题标题】:How do I achieve the following Tkinter GUI layout with either pack or grid?如何使用包或网格实现以下 Tkinter GUI 布局?
【发布时间】:2011-06-14 17:24:33
【问题描述】:

这是我当前的跳棋游戏 GUI 布局:

如您所见,它由顶部的菜单、左侧用于绘制棋盘的画布、右上角的工具栏(框架)和文本小部件组成用于注释动作。目前,我正在为小部件使用网格布局。

这是我需要做的:

  1. 当文本量大于小部件大小时,能够在文本小部件中显示/隐藏滚动条。 (根据this article,这似乎需要网格布局。)
  2. [通过首选项对话框] 更改文本小部件中文本的字体和/或大小,并且不要在文本小部件周围留下奇怪的间隙。 (这似乎需要一个包布局,因为 Text 小部件只能以字符而不是像素为单位给出宽度和高度......这意味着当我更改字体或大小时 Text 小部件会增长或缩小,并且窗口不会调整以适应网格布局。我一直在尝试使用 Font.measure 根据所选字体调整 Text 小部件的大小,但我仍然有间隙,因为我无法将小部件的大小调整到确切的像素。)
  3. 我的最终解决方案需要是跨平台的(Windows 和 Linux,最好是 Mac)。

我可以使用哪种布局来满足我的要求?如果两者都不能完全工作,哪种布局(网格或包)会让我最接近我的目标?谢谢!

【问题讨论】:

  • 网格布局具有与打包相同的增长/收缩行为,只是访问方式不同(赋予行和/或列“权重”)
  • 您的屏幕截图显示了一个非标准菜单栏,它一直延伸。这是一个要求,还是标准菜单栏可以?

标签: python layout grid tkinter pack


【解决方案1】:

对于这个简单的布局,您可以使用gridpack 或两者。在这种特殊情况下,两者都没有明显的优势。两者都具有您想要的调整大小行为。

在我的头顶上,我会使用一个水平框架来固定按钮,然后将按钮打包。然后我可能会使用网格将工具栏、文本小部件和滚动条放置在框架内。包也可以使用,两者都可以。这会照顾到右侧。

如果你想要图片中的菜单栏(即:非标准,仅在棋盘上方),我会使用类似的技术:左侧的另一个框架,菜单栏位于顶部,棋盘位于底部。

然后我会在主窗口中使用 pack,底部是状态栏,左侧是棋盘,右侧是文本区域。

但是,最好使用标准菜单栏,这意味着您不需要为棋盘/菜单栏组合提供包含框架

以下是使用标准菜单栏的一种解决方案的快速破解方法。这使用了将大多数小部件作为父级的子级的技术,然后使用in_ 参数将它们放入容器中。这使得以后更改布局变得更加容易,因为您不必更改整个层次结构,而只需更改小部件在容器中的位置。

import Tkinter as tk
import random

class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        size = 40
        menubar = tk.Menu(self)
        menubar.add_cascade(label="Game")
        menubar.add_cascade(label="Options")
        menubar.add_cascade(label="Help")
        chessboard = tk.Canvas(width=8*size, height=8*size, borderwidth = 0,
                               highlightthickness=0)
        statusbar = tk.Label(self, borderwidth=1, relief="sunken")
        right_panel = tk.Frame(self, borderwidth = 1, relief="sunken")
        scrollbar = tk.Scrollbar(orient="vertical", borderwidth=1)
        # N.B. height is irrelevant; it will be as high as it needs to be
        text = tk.Text(background="white",width=40, height=1, borderwidth=0, yscrollcommand=scrollbar.set)
        scrollbar.config(command=text.yview)

        toolbar = tk.Frame(self)
        for i in range(10):
            b = tk.Button(self, text="B%s" % i, borderwidth=1)
            b.pack(in_=toolbar, side="left")

        self.config(menu=menubar)
        statusbar.pack(side="bottom", fill="x")
        chessboard.pack(side="left", fill="both", expand=False)
        toolbar.grid(in_=right_panel, row=0, column=0, sticky="ew")
        right_panel.pack(side="right", fill="both", expand=True)
        text.grid(in_=right_panel, row=1, column=0, sticky="nsew")
        scrollbar.grid(in_=right_panel, row=1, column=1, sticky="ns")
        right_panel.grid_rowconfigure(1, weight=1)
        right_panel.grid_columnconfigure(0, weight=1)

if __name__ == "__main__":
    app = App()
    app.mainloop()

【讨论】:

  • 布莱恩,感谢您的帮助。我从来不知道你可以在同一个窗口中混合包和网格,只要它们在不同的容器中。我也不知道在网格中使用权重。
  • @Brandon:我一直在混合几何管理器。这确实是唯一的工作方式,因为每种方式都有其优点和缺点。将自己限制在一个范围内是……呃……限制。请注意不要在同一个容器中同时使用 grid 和 pack,这会出现问题。
猜你喜欢
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-16
相关资源
最近更新 更多