如何在 Python3/tkinter with grid 中创建具有 3 个框架和动态布局的简单 window?

How to create a simple window with 3 frames and dynamic layout in Python3 / tkinter with grid?

我正在 Python3 探索 tkinter,并且刚刚开始我的第一个 GUI 项目。我正在尝试使用网格定位系统和 3 个框架来创建一个简单的布局,如下所示:

我一直在摆弄框架和重量,似乎总是出问题。如果我将 window 调整得足够小,主框架会部分隐藏顶部框架。如果我放大 window,主框架和树视图不会按预期一直向下展开。有人可以帮忙吗?

这是我现在拥有的代码:

#!/usr/local/bin/python3
# encoding: utf-8
"""
docstring
"""

import sys
import os
import os.path
import csv
import re
from platform import node


from tkinter import *
from tkinter import ttk


__app_name__ = "APP NAME"
__version__ = "0.0.1"


def add_remessa():
    pprint("REMESSA")


def click_btn_hoje():
    print("HOJE")


root = Tk()
root.title(__app_name__+" "+__version__)
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)

topframe = ttk.Frame(root, padding="3 3 12 12")
topframe.grid(column=0, row=0, sticky=(N, E, W))
topframe.columnconfigure(0, weight=1)
topframe.columnconfigure(1, weight=1)
topframe.rowconfigure(0, weight=1)
topframe.rowconfigure(0, weight=1)

mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=1, sticky=(N, W, E))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)

bottomframe = ttk.Frame(root, padding="3 3 12 12")
bottomframe.grid(column=0, row=2, sticky=(W, E, S))
bottomframe.columnconfigure(0, weight=1)
bottomframe.columnconfigure(1, weight=1)
bottomframe.rowconfigure(0, weight=1)
bottomframe.rowconfigure(0, weight=1)


def NovaRemessa():
    print("Nova remessa!")
def EditarRemessa():
    print("Editar")
def About():
    print("This is a simple example of a menu")
def painelAddRemessa():
        print("Mostrar painel de introdução de nova remessa")


btn_quit = ttk.Button(topframe, text="+", command=painelAddRemessa)
btn_quit.grid(row=0, column=6, sticky=E+N)

btn_quit = ttk.Button(topframe, text="  Sair  ", command=exit)
btn_quit.grid(row=0, column=1, sticky=E+N)

# Data entry form
obj_num = StringVar()
destin = StringVar()
cobr = StringVar()
dias = StringVar()
vols = StringVar()

ttk.Label(bottomframe, text="Nº Objeto").grid(row=5, column=0, sticky=W+S)
text_input_obj = ttk.Entry(bottomframe,textvariable=obj_num, width=13)
text_input_obj.grid(row=6, column=0, sticky=W+S)
text_input_obj.focus_set()

ttk.Label(bottomframe, text="Destinatário").grid(row=5, column=1, columnspan=1, sticky=W+S)
text_input_dest = ttk.Entry(bottomframe, textvariable=destin, width=25)
text_input_dest.grid(row=6, column=1, sticky=W+S)

ttk.Label(bottomframe, text="Cobrança").grid(row=5, column=2, sticky=W+E+S)
text_input_cobr = ttk.Entry(bottomframe, textvariable=cobr, width=7)
text_input_cobr.grid(row=6, column=2, sticky=W+E+S)

ttk.Label(bottomframe, text="Dias").grid(row=5, column=3, sticky=W+E+S)
text_input_dias = ttk.Entry(bottomframe, textvariable=dias, width=4)
text_input_dias.grid(row=6, column=3, sticky=W+E+S)

ttk.Label(bottomframe, text="Volumes").grid(row=5, column=4, sticky=W+E+S)
text_input_vols = ttk.Entry(bottomframe, textvariable=vols, width=5)
text_input_vols.grid(row=6, column=4, sticky=W+E+S)

# Botões
btn_add = ttk.Button(bottomframe, text="  Adicionar  ", command=add_remessa).grid(row=6, column=6,sticky=W+E+S)


ttk.Label(mainframe, text="Nº de remessas: XXXX").grid(row=2, column=0, columnspan=2, sticky=W)
ttk.Label(mainframe, text="Valor a cobrar: XXXXXX").grid(row=2, columnspan=2, column=2)
ttk.Label(mainframe, text="Recebido: XXXXX").grid(row=2, column=4)
ttk.Label(mainframe, text="Depositar: XXXXXXX").grid(row=2, column=6, sticky=E)

tree = ttk.Treeview(mainframe, selectmode='extended')
tree['columns'] = ('ID', 'Dias', 'Destinatário', 'Estado', 'Objeto nº', 'Cobr.', 'Chq.rec.', 'Depositar')
tree.grid(row=0, column=0, columnspan=7, sticky=N+W+E+S)
tree.column('#0', anchor=W, minwidth=0, stretch=0, width=0)
tree.column('ID', anchor=W, minwidth=30, stretch=1, width=30)
tree.column('Dias', minwidth=30, stretch=1, width=30)
tree.column('Destinatário', minwidth=100, stretch=1, width=200)
tree.column('Estado', minwidth=100, stretch=1, width=180)
tree.column('Objeto nº', minwidth=50, stretch=1, width=80)
tree.column('Cobr.', minwidth=60, stretch=1, width=60)
tree.column('Chq.rec.', minwidth=80, stretch=1, width=80)
tree.column('Depositar', anchor=E, minwidth=80, stretch=1, width=80)
tree.heading('ID', text="ID")
tree.heading('Dias', text="Dias")
tree.heading('Destinatário', text="Destinatário")
tree.heading('Estado', text="Estado")
tree.heading('Objeto nº', text="Objeto nº")
tree.heading('Cobr.', text="Cobr.")
tree.heading('Chq.rec.', text="Chq.rec.")
tree.heading('Depositar', text="Depositar")

for child in mainframe.winfo_children(): child.grid_configure(padx=1, pady=1)

mainloop()

你忽略了一些事情。首先,您将所有权重赋予根 window 的第 0 行。由于您希望主要区域占用所有额外的区域 space,因此您需要将权重分配给第 1 行。

其次,您没有对主框架内的行和列赋予任何权重。由于您希望树(我假设)填充 space,因此您必须为树的行和列赋予权重。


忠告:不要试图一次解决所有布局问题。重新启动您的程序,并在根目录中只创建三个框架:顶部、中间和底部。暂时给每个人一个独特的颜色,这样你就可以区分他们。然后,用 pack 或 grid 对它们进行布局,并确保在调整 window 大小时这些区域会适当地增长和收缩。

只有在这三个区域正常运行后,您才应尝试将小部件仅添加到其中一个框架。确保在调整 window 大小时一切正常。然后添加下一帧,再次确保在继续下一个问题之前一切正常。

您还应该考虑将 pack 用于您的部分 GUI。当您将东西从上到下或从一侧到另一侧堆叠时,pack 可以说是更好的选择。如果我正在编写这段代码,我会对三个主要框架使用 pack,对每个框架内的小部件使用 grid