¿Qué es un administrador de geometría Tkinter mejor que .grid ()?

Mi queja

Actualmente estoy profundizando más que nunca en la GUI de Tkinter, y he encontrado que el administrador de geometría .grid() es inadecuado por varios motivos:

  1. Las gráficas se basan en el widget más grande dentro de ellas: esta relatividad lleva a la inexactitud.

  2. En Windows 7, en Python 2.7.3, el progtwig no parece prestar atención a mis números de fila, sino que prefiere usar el orden de los widgets.

Mi código

Actualmente estoy trabajando en un editor de texto muy básico, y quiero tener varios botones en la parte superior del marco. No he podido hacer esto porque mis widgets se colocan a la izquierda o derecha del cuadro de texto masivo que domina el centro de la pantalla.

 ========Class __init__ Stuff============ def widget(self):#Place widgets here #Save Button self.saveButton = Button (self, text = "Save", command = self.saveMe) self.saveButton.grid(column = 0, row = 0, sticky = W) #Open Button self.openButton = Button (self, text = "Open", command = self.openMe) self.openButton.grid(column = 0, row = 1, sticky = W) #Area where you write self.text = Text (self, width = (root.winfo_screenwidth() - 20), height = (root.winfo_screenheight() - 10)) self.text.grid(row = 2) ==============Mainloop/Command Stuff============ 

Mi pregunta

¿Hay otra forma de usar el administrador de geometría .grid() de una manera más precisa, o debería estar usando otra función por completo?

¡Gracias!

Hay 3 administradores de geometría que tiene disponibles para usted: grid , pack y place . El tercero es el más general, pero también muy difícil de usar. Prefiero grid . Tenga en cuenta que puede colocar widgets dentro de otros widgets, o puede especificar el columnspan . Por lo tanto, si desea obtener el siguiente diseño:

  ------------------------- | Button1 | Button2 | ------------------------- | Big Widget | ------------------------- 

Hay 2 formas canónicas de hacerlo usando .grid . El primer método es columnspan :

 import Tkinter as Tk root = Tk.Tk() b1 = Tk.Button(root,text="Button1") b1.grid(row=0,column=0) b2 = Tk.Button(root,text="Button2") b2.grid(row=0,column=1) big_widget = Tk.Canvas(root) big_widget.grid(row=1,column=0,columnspan=2) 

* Tenga en cuenta que también hay una opción de rowspan completamente análoga.

El segundo método es usar un Frame para mantener tus botones:

 import Tkinter as Tk root = Tk.Tk() f = Tk.Frame(root) f.grid(row=0,column=0) #place buttons on the *frame* b1 = Tk.Button(f,text="Button1") b1.grid(row=0,column=0) b2 = Tk.Button(f,text="Button2") b2.grid(row=0,column=1) big_widget = Tk.Canvas(root) big_widget.grid(row=1,column=0) #don't need columnspan any more. 

Este método es SUPER útil para crear diseños complejos. No sé cómo se podría crear un diseño complejo sin usar objetos Frame como este …

El “mejor” administrador de geometría depende de lo que quiera hacer, ningún administrador de geometría es el mejor para todas las situaciones. Por lo que está tratando de hacer en este caso específico, el paquete es probablemente la mejor opción. También tenga en cuenta que puede haber más de un “mejor” en una aplicación. Es bastante normal utilizar tanto la red como el paquete en diferentes partes de sus aplicaciones. Rara vez creo una GUI en la que no use tanto grid como pack. Y raramente, también uso lugar.

Paquete sobresale en la colocación de las cosas en filas individuales y columnas individuales. Las barras de herramientas, por ejemplo, son un caso perfecto para usar el paquete, ya que quieres que todos tus botones estén alineados a la izquierda. La cuadrícula, como su nombre lo indica, es mejor cuando se quieren filas y columnas fijas. El lugar es útil en aquellos casos raros en los que ni la cuadrícula ni el paquete funcionarán, ya que le permite colocar widgets en ubicaciones fijas o relativas precisas.

Mi consejo es dividir los widgets de la aplicación en grupos y usar el administrador de geometría adecuado para cada grupo. En su caso, tiene dos grupos lógicos: la barra de herramientas en la parte superior y una combinación de texto-widget-y-barra de desplazamiento en la parte inferior. Entonces, comienza con dos marcos. Dado que la barra de herramientas está en la parte superior y el widget de texto está debajo, el paquete funciona mejor.

 toolbar = tk.Frame(...) main = tk.Frame(...) toolbar.pack(side="top", fill="x", expand=False) main.pack(side="bottom", fill="both", expand=True) 

Lo anterior ahora le da dos áreas que son fáciles de modificar independientemente.

Para la barra de herramientas, el paquete es nuevamente más natural. En este caso, sin embargo, desea que los botones se encuentren a la izquierda en lugar de a lo largo de la parte superior o inferior:

 b1 = tk.Button(toolbar, ...) b2 = tk.Button(toolbar, ...) b1.pack(side="left") b2.pack(side="left") ... 

Finalmente, el área inferior. Su código de ejemplo no muestra barras de desplazamiento, pero supongo que en algún momento querrá agregarlas. la cuadrícula funciona bien si utiliza barras de desplazamiento tanto horizontales como verticales. Los pondría así:

 hsb = tk.Scrollbar(main, ..., orient="horizontal", ...) vsb = tk.Scrollbar(main, ..., orient="vertical", ...) text = tk.Text(main, ...) vsb.grid(row=0, column=1, sticky="ns") hsb.grid(row=1, column=0, sticky="ew") text.grid(row=0, column=0, sticky="nsew") main.grid_rowconfigure(0, weight=1) main.grid_columnconfigure(0, weight=1) 

La última parte es importante: siempre debe asignar un peso a al menos una fila y una columna. Esto le indica a la cuadrícula qué filas y columnas deben crecer y reducirse cuando se cambia el tamaño de la ventana.

Considero que el gestor de lugares es el más intuitivo y preciso de los tres, debido a la posibilidad de especificar combinaciones de longitudes absolutas y relativas para ambas posiciones y tamaño:

 mywidget.place(x=..., y=..., width=..., height=...) # absolute mywidget.place(relx=..., rely=..., relwidth=..., relheight=...) # relative # combination pad_left=5 pad_right=5 pad_top=5 pad_bottom=5 mywidget.place(relx=0, x=pad_left, rely=0, y=pad_top,\ relwidth=1, width=-pad_left-pad_right,\ relheight=1, height=-pad_top-pad_bottom, anchor="e") # use the whole space except some padding 

Por alguna razón, el administrador de .place no parece muy querido, pero creo que hace un buen trabajo en particular para definir cómo deben moverse y cambiar el tamaño de los widgets cuando se cambia el tamaño de la ventana principal.

Para facilitar la construcción de ventanas complejas, a veces uso una función (para simular un comportamiento de cuadrícula, supongo) para ayudar en la colocación vertical, como:

 def offset_y(line_no): if line_no == 0: return 0 else: return height_label + (line_no - 1)*height_button mylabel.place(..., y=offset_y(0)) mybtn1.place(..., y=offset_y(1)) etc. 

para empacar verticalmente una etiqueta y luego una serie de botones. (Por supuesto, el administrador de .pack podría usarse en este caso, pero la razón por la que prefiero el administrador de .place es para entender con mayor precisión cómo se moverán las cosas cuando se cambie el tamaño de la ventana).

En lugar de fila, columna … etc., puedes usar coordenadas.

Puede ser más fácil que los demás.

EJEMPLO:

 from Tkinter import* root=Tk() Button(root,text="HI").grid(padx=100,pady=50) root.mainloop() 

Pruébelo usted mismo cambiando los valores de padx y pady.