【问题标题】:Tkinter multi-frame resizeTkinter 多帧调整大小
【发布时间】:2012-11-07 15:26:58
【问题描述】:

我有一台可以理解多种串行协议的设备。在开发过程中,我创建了简单的 Tkinter UI 来使用协议。每个协议都有一个新的 UI。由于协议有很多命令,我在一个可滚动的画布中实现了整个 UI,以便在较小的显示器上使用时可以滚动它。单独的 UI 运行良好,我现在正尝试将单独的 UI 组合成一个选项卡式 UI。

每个 UI 的共同元素是串口选择器,我将其分离出来并放在单独的顶部框架中。然后我实现了一个笔记本,并将每个协议 UI 放入每个选项卡的框架中。

但我无法正确控制大小:我希望将根窗口宽度固定为任何协议框架或串行选择器框架的最大宽度,并禁用水平调整大小。我希望串行选择器始终存在,并且在垂直调整窗口大小时不受影响(仅调整笔记本大小/滚动)。

以下是我目前所拥有的。所有部分都存在,但笔记本没有填满整个窗口宽度,并且在调整窗口大小时笔记本不会调整大小(调整大小只会增加空白)。

def main():
    ## Main window
    root = Tkinter.Tk()
    root.title("Multi-Protocol UI")

    ## Grid sizing behavior in window
    root.grid_rowconfigure(0, weight=0)
    root.grid_rowconfigure(1, weight=1)
    root.grid_columnconfigure(0, weight=1)
    root.grid_columnconfigure(1, weight=0)

    ## Window content
    upper = ttk.Frame(root)   # Serial port selector
    upper.grid(row=0)
    upper.grid_rowconfigure(0, weight=0)
    upper.grid_columnconfigure(0, weight=1)
    upper.grid_columnconfigure(1, weight=0)
    lower = ttk.Frame(root)   # For protocols
    lower.grid(row=1)
    lower.grid(row=1, sticky='nswe')
    lower.grid_rowconfigure(0, weight=1)
    lower.grid_columnconfigure(0, weight=1)
    lower.grid_columnconfigure(1, weight=0)

    # Setup serial control frame
    serial = SerialFrame(master=upper)  # Serial port selector widget + Open button

    ## Protocol GUIs are large: Use a form within a scrollable canvas.
    cnv = Tkinter.Canvas(lower)
    cnv.grid(row=0, column=0, sticky='nswe')
    cnv.grid_rowconfigure(0, weight=1)
    cnv.grid_columnconfigure(0, weight=1)
    cnv.grid_columnconfigure(1, weight=0)
    # Scrollbar for canvas
    vScroll = Tkinter.Scrollbar(
        lower, orient=Tkinter.VERTICAL, command=cnv.yview)
    vScroll.grid(row=0, column=1, sticky='ns')
    cnv.configure(yscrollcommand=vScroll.set)
    # Frame in canvas
    window = Tkinter.Frame(cnv)
    window.grid()
    # Put the frame in the canvas's scrollable zone
    cnv.create_window(0, 0, window=window, anchor='nw')

    # Setup the notebook (tabs) within the scrollable window
    notebook = ttk.Notebook(window)
    frame1 = ttk.Frame(notebook)
    frame2 = ttk.Frame(notebook)
    notebook.add(frame1, text="ProtoA")
    notebook.add(frame2, text="ProtoB")
    notebook.grid(row=0, column=0, sticky='nswe')

    # Create tab frames
    protoA = ProtoAFrame(master=frame1)
    protoA.grid()
    protoA.update_idletasks()
    protoB = ProtoBFrame(master=frame2)
    protoB.grid()
    protoB.update_idletasks()

    ## Update display to get correct dimensions
    root.update_idletasks()
    window.update_idletasks()
    ## Configure size of canvas's scrollable zone
    cnv.configure(scrollregion=(0, 0, window.winfo_width(), window.winfo_height()))

    # Not resizable in width:
    root.resizable(width=0, height=1)

    ## Go!
    root.mainloop()

如何锁定顶部串行框架,将笔记本电脑扩展至全宽,并强制调整窗口大小以仅影响笔记本电脑框架?我是 Tkinter 新手,所以如果我遗漏了一些“明显”的东西,请保持温柔。

TIA!

【问题讨论】:

  • 部分进度:在根窗口中,我需要将顶部框架的行配置权重设置为 0,将底部框架设置为 1。上面的源代码已更新。但是笔记本仍然没有扩展以填充下框架。咕噜。
  • 我已将 rowconfigure 和 columnconfigure 添加到所有帧,并实现了许多所需的行为。但默认窗口宽度是相当窄的顶部框架的宽度,而不是最宽的笔记本选项卡的宽度。
  • 我目前对宽度问题的处理是填充顶部窗口。不漂亮,但效果很好。

标签: python resize tkinter frame scrollable


【解决方案1】:

您有嵌套在小部件内的小部件。即使您将笔记本设置为在其容器中正确展开,您也需要确保向上的每个容器也正确展开。你没有这样做。例如,问问自己画布是否已设置为在lower 内正常增长。

既然你刚开始,这是我推荐的。与其试图一次把所有事情都做好,不如选择“分而治之”的方法。首先,为 GUI 的主要区域创建框架。除了那些框架,什么都不做,并让它们的调整大小行为完全符合您的要求。在此阶段为每个小部件赋予自己的颜色会有所帮助,这样您就可以清楚地看到小部件的位置。您以后可以随时更改颜色。此外,如果您只有几个小部件,或者您的所有小部件都是水平或垂直方向的,那么包通常比网格更容易使用。

例如:

upper.pack(side="top", fill="x", expand=False)
lower.pack(side="bottom", fill="both", expand=True)

一旦您对这些主要部分进行了适当调整,就可以解决其中一个区域的问题了。选择一个区域,然后做同样的事情:添加它的子小部件,或者如果您在一个区域中有区域,则细分为框架。一旦你有这个工作,泡沫,冲洗,重复。

【讨论】:

  • 网格几何管理器默认不这样做吗?或者,等效地,我将如何使用网格来做到这一点?如果可能,我宁愿不混合几何管理器。
  • 不,网格几何管理器默认赋予其所有行和列的权重 0(零)。此外,不要害怕混合几何管理器,只要您在单独的容器中使用它们就不是问题。我不知道我是否曾经写过一个不使用 pack 和 grid 的 GUI(并且我写过 lot)。
  • 我明白了。我真的只需要我的低级小部件的网格管理器。我也可以使用 pack 作为滚动条吗?还是我应该仍然网格化。
  • 一帧内的所有东西都只需要使用网格,或者只需要打包。不同的框架(或画布,或顶层等)可以使用任何有意义的东西。有时如果所有内容都在单行或单列中,则打包会更好,当应将事物布置在网格中时,网格才有意义。任何一个都可以正常工作时,会有很多灰色区域。
  • 嗯...使用 pack,我的笔记本不会填充下框架,就像使用带有 rowconfigure/columnconfigure 的网格时一样。
猜你喜欢
  • 2016-06-29
  • 1970-01-01
  • 2011-03-31
  • 2021-11-29
  • 1970-01-01
  • 2020-11-22
  • 2013-05-07
  • 2017-12-29
  • 1970-01-01
相关资源
最近更新 更多