web-dev-qa-db-fra.com

tkinter gui layout utilisant des cadres et une grille

Mon mise en page graphique

gui layout

ressemble presque rien comme ce que j'attends

what I expect

donc je suppose qu'il y a des bases que je ne comprends pas.

J'ai supposé que les cadres contenaient leur propre "espace de grille" (ligne, colonne), mais le comportement que je vois ne le confirme pas, et je suis incapable de faire en sorte que les choses fonctionnent comme je le souhaite pour le cadre du haut. Mes étiquettes sont supposées se trouver sur la même ligne de gauche à droite, sous une "étiquette de cadre" qui couvre l'intégralité de l'image - sauf qu'elles ne le font pas. Je veux que l'actuel ressemble davantage à l'objectif jpg et je veux utiliser une grille pour le faire.

Vous pouvez simplement voir l'un des champs de saisie à droite du cadre vert. Pourquoi y va-t-il?

from Tkinter import *

root = Tk()
root.title('Model Definition')
root.resizable(width=FALSE, height=FALSE)
root.geometry('{}x{}'.format(460, 350))

top_frame = Frame(root, bg='cyan', width = 450, height=50, pady=3).grid(row=0, columnspan=3)
Label(top_frame, text = 'Model Dimensions').grid(row = 0, columnspan = 3)
Label(top_frame, text = 'Width:').grid(row = 1, column = 0)
Label(top_frame, text = 'Length:').grid(row = 1, column = 2)
entry_W = Entry(top_frame).grid(row = 1, column = 1)
entry_L = Entry(top_frame).grid(row = 1, column = 3)
#Label(top_frame, text = '').grid(row = 2, column = 2)

center = Frame(root, bg='gray2', width=50, height=40, padx=3, pady=3).grid(row=1, columnspan=3)
ctr_left = Frame(center, bg='blue', width=100, height=190).grid(column = 0, row = 1, rowspan = 2)
ctr_mid = Frame(center, bg='yellow', width=250, height=190, padx=3, pady=3).grid(column = 1, row=1, rowspan=2)
ctr_right = Frame(center, bg='green', width=100, height=190, padx=3, pady=3).grid(column = 2, row=1, rowspan=2)

btm_frame = Frame(root, bg='white', width = 450, height = 45, pady=3).grid(row = 3, columnspan = 3)
btm_frame2 = Frame(root, bg='lavender', width = 450, height = 60, pady=3).grid(row = 4, columnspan = 3)


root.mainloop()

Dans ce cas précis, où sont allées mes étiquettes et les widgets Entry, et comment puis-je les amener à ressembler davantage à l'objectif (cadre supérieur, le reste appartient à plus tard).

20
shawn

J'ai supposé que les cadres contenaient leur propre "espace de grille"

C'est une hypothèse correcte.

Vous pouvez simplement voir l'un des champs de saisie à droite du cadre vert. Pourquoi y va-t-il?

Le problème commence ici:

top_frame = Frame(root, ...).grid(row=0, ...)

En python, x = y().z() affectera toujours x au résultat de .z(). Dans le cas de top_frame = Frame(...).grid(...), grid(...) renvoie toujours None afin que top_frame Soit None. Cela fait que tous les widgets que vous pensez vont dans le cadre du haut vont réellement dans la fenêtre racine.

Vue d'ensemble de la solution

En règle générale, vous devriez ne jamais appeler grid, pack ou place comme partie de la même déclaration qui crée le widget. En partie c'est pour ce comportement que vous rencontrez, mais aussi parce que je pense que cela rend votre code plus difficile à écrire et à maintenir au fil du temps.

La création de widgets et la présentation de widgets sont deux choses différentes. D'après mon expérience, les problèmes de présentation sont considérablement plus faciles à résoudre lorsque vous regroupez vos commandes de présentation.

En outre, vous devez être cohérent lorsque vous utilisez la grille et placez toujours les options dans le même ordre afin de pouvoir visualiser plus facilement la mise en page. Enfin, lorsque vous utilisez grid, vous devez prendre l’habitude de toujours spécifier l’option sticky et de toujours attribuer un poids non nul à une ligne et à une colonne dans chaque cadre.

Exemple de solution

Voici comment j'écrirais votre code. C'est beaucoup plus long, mais beaucoup plus facile à comprendre.

from Tkinter import *

root = Tk()
root.title('Model Definition')
root.geometry('{}x{}'.format(460, 350))

# create all of the main containers
top_frame = Frame(root, bg='cyan', width=450, height=50, pady=3)
center = Frame(root, bg='gray2', width=50, height=40, padx=3, pady=3)
btm_frame = Frame(root, bg='white', width=450, height=45, pady=3)
btm_frame2 = Frame(root, bg='lavender', width=450, height=60, pady=3)

# layout all of the main containers
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=1)

top_frame.grid(row=0, sticky="ew")
center.grid(row=1, sticky="nsew")
btm_frame.grid(row=3, sticky="ew")
btm_frame2.grid(row=4, sticky="ew")

# create the widgets for the top frame
model_label = Label(top_frame, text='Model Dimensions')
width_label = Label(top_frame, text='Width:')
length_label = Label(top_frame, text='Length:')
entry_W = Entry(top_frame, background="pink")
entry_L = Entry(top_frame, background="orange")

# layout the widgets in the top frame
model_label.grid(row=0, columnspan=3)
width_label.grid(row=1, column=0)
length_label.grid(row=1, column=2)
entry_W.grid(row=1, column=1)
entry_L.grid(row=1, column=3)

# create the center widgets
center.grid_rowconfigure(0, weight=1)
center.grid_columnconfigure(1, weight=1)

ctr_left = Frame(center, bg='blue', width=100, height=190)
ctr_mid = Frame(center, bg='yellow', width=250, height=190, padx=3, pady=3)
ctr_right = Frame(center, bg='green', width=100, height=190, padx=3, pady=3)

ctr_left.grid(row=0, column=0, sticky="ns")
ctr_mid.grid(row=0, column=1, sticky="nsew")
ctr_right.grid(row=0, column=2, sticky="ns")

root.mainloop()

Résultat:

screenshot of running example

35
Bryan Oakley

variable = Widget(...).grid() assigne None à une variable car grid()/pack()/place() return None

utilisation

variable = Widget(...)
variable.grid() # .pack() .place()
2
furas