简体   繁体   English

如何在带有网格的Python3 / tkinter中创建具有3帧和动态布局的简单窗口?

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

I am exploring tkinter in Python3 and have just started my first GUI project. 我正在Python3中探索tkinter,并且刚刚开始了我的第一个GUI项目。 I am trying to use the grid positioning system and 3 frames to create a simple layout like this: 我正在尝试使用网格定位系统和3个框架来创建一个简单的布局,如下所示:

  • Top frame: tool bar, some buttons, maybe a search field (should be always visible and stick to the top of the window and extend all across left to right). 顶部框架:工具栏,一些按钮,也许是搜索字段(应始终可见,并粘贴在窗口顶部,并从左到右延伸)。
  • Main frame: treeview, intended to retrieve values from a database (should stick to the top, right below the top frame, expanding from left to right, and should also expand to take all the space left by top and bottom frames). 主框架:树状视图,用于从数据库中检索值(应坚持到顶部,在顶部框架的正下方,从左向右扩展,并且还应该扩展以占据顶部和底部框架剩下的所有空间)。
  • Bottom frame: data entry form, status bar... (should stick to the bottom of the window, expanding from left to right, and leave space to the main frame. 底框:数据输入表单,状态栏...(应粘贴到窗口底部,从左向右扩展,并留出空间留给主框架。

I have been messing around with frames and weights and it seems to be always something wrong. 我一直在搞乱框架和重量,这似乎总是有问题。 If I resize the window small enough, the main frame hides partially the top frame. 如果我将窗口的大小调整得足够小,则主框架会部分隐藏顶部框架。 If I enlarge the window, the main frame and the treeview does not expand all the way down as intended. 如果放大窗口,则主框架和树形视图不会完全按照预期的方式向下扩展。 Can anyone please help? 谁能帮忙吗?

Here is my code as I have it right now: 这是我现在拥有的代码:

#!/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()

You are neglecting to do a couple of things. 您忽略了做几件事。 First, you are giving all of the weight to row 0 of the root window. 首先,将所有权重赋予根窗口的第0行。 Since you want the main area to take up all the extra space you need to give the weight to row 1. 由于您希望主要区域占用所有多余的空间,因此需要为第1行赋予权重。

Second, you aren't giving any weight to the rows and columns inside the main frame. 其次,您不会对主框架内的行和列施加任何权重。 Since you want the tree (I assume) to fill the space, you must give the row and column of the tree a weight. 由于要让树(我假设)填充空间,因此必须给树的行和列赋予权重。


A word of advice: don't try to solve all of your layout problems at once. 忠告:不要试图立即解决所有布局问题。 Start your program over, and create just the three frames in root: top, middle and bottom. 重新开始程序,并在根目录中仅创建三个框架:顶部,中间和底部。 Temporarily give each one of them a distinctive color so you can distinguish them. 暂时为它们中的每一个赋予独特的颜色,以便您可以区分它们。 Then, lay them out with pack or grid, and make sure when you resize the window that those areas grow and shrink appropriately. 然后,将它们与包装或网格一起布置,并确保在调整窗口大小时可以适当地增大和缩小这些区域。

Only after you have those three areas behaving properly should you attempt to add widgets to only one of those frames. 只有在这三个区域的行为均正确之后,才应尝试将窗口小部件仅添加到这些框架之一。 Make sure when you resize the window that everything continues to work. 确保在调整窗口大小时一切都可以正常工作。 Then add the next frame, again making sure it is all working before continuing to the next problem. 然后添加下一个框架,再次确认所有框架都可以正常工作,然后再继续下一个问题。

You should also consider using pack for part of your GUI. 您还应该考虑将pack用于部分GUI。 pack is an arguably better choice when you have things stacked top-to-bottom or side-to-side. 当您将东西从上到下或从一侧到另一侧堆叠时, pack是一个更好的选择。 If I were writing this code I'd use pack for the three main frames, and grid for the widgets inside each frame. 如果要编写此代码,则将pack用于三个主要框架,并将grid用于每个框架内的小部件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM