Problème de grille Tkinter - Cadres non alignés
Je viens de commencer à travailler avec tkinter et j'essaie toujours de m'habituer à son fonctionnement. J'essayais de préparer une sorte de menu en grille avec 4 sections.
Il y a un cadre en haut avec le titre de l'application, un cadre à gauche avec quelques boutons pour configurer l'application, puis 4 cadres de taille égale dans le reste.
Mon problème principal ici est la colonne vide entre le cadre de gauche et les quatre autres, comment puis-je ajuster cela pour que les 4 carrés remplissent cet espace?
Voir ci-dessous le code:
import datetime
import tkinter as tk
from time import strftime
window = tk.Tk()
window.geometry("1400x800")
window.configure(bg="white")
window.rowconfigure(20,weight=1)
window.columnconfigure(35,weight=1)
window.title("Hello World App")
entry_var_server = tk.StringVar(window,"")
entry_var_db = tk.StringVar(window,"")
entry_var_driver = tk.StringVar(window,"")
def window_widgets():
db_ini_frame_top = tk.Frame(master=window,bg="#57b956",height=120,width=1400,highlightbackground="black",highlightthickness=2)
db_ini_frame_top.grid(rowspan=3,columnspan=34,sticky="w")
db_ini_label_top = tk.Label(master=window,text="Hello World",bg="#57b956")
db_ini_label_top.configure(font=("Calibri",26))
db_ini_label_top.grid(row=1,column=18,sticky="n")
def cur_date(dic = {'01':'st','21':'st','31':'st',
'02':'nd','22':'nd',
'03':'rd','23':'rd'}):
x = strftime('%A, %B %d')
return x + dic.get(x[-2:],'th')+strftime(" %G - %H:%M")
date = cur_date()
db_ini_date = tk.Label(master=window,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,sticky="w")
db_ini_frame_left = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_frame_left.grid(row=3,rowspan=16,columnspan=2,sticky="w")
db_ini_frame_center_nw = tk.Frame(master=window,height=350,width=640,bg="blue")
db_ini_frame_center_nw.grid(row=3,column=3,columnspan=16,rowspan=12,sticky="nw")
db_ini_frame_center_sw = tk.Frame(master=window,height=450,width=640,bg="light blue")
db_ini_frame_center_sw.grid(row=12,column=3,columnspan=16,rowspan=12,sticky="sw")
db_ini_frame_center_ne = tk.Frame(master=window,height=350,width=640,bg="light blue")
db_ini_frame_center_ne.grid(row=3,column=19,columnspan=16,rowspan=12,sticky="ne")
db_ini_frame_center_se = tk.Frame(master=window,height=450,width=640,bg="blue")
db_ini_frame_center_se.grid(row=12,column=19,columnspan=16,rowspan=12,sticky="se")
window_widgets()
window.tk.mainloop()
Réponses
Bien que nous puissions corriger votre code avec seulement quelques petits changements, prendre quelques minutes pour créer une mise en page plus intelligente facilitera grandement la modification de votre code à mesure que l'application se développe.
Je vais offrir quelques conseils sur la façon dont je réorganiserais votre code. À la fin de la réponse se trouve un dernier exemple de travail. 90% de celui-ci est votre code d'origine, mais avec quelques ajustements ici et là pour faciliter la création de l'interface utilisateur.
Ne pas utiliser gridpour tout
Tout d'abord, je vous recommande de ne pas l' utiliser gridpour tout. C'est bien pour créer des grilles, mais il existe parfois de meilleures façons de disposer une fenêtre entière. Divisez votre interface utilisateur en regroupements logiques, puis disposez-les en utilisant ces regroupements.
En organisant votre interface utilisateur en sections, il est beaucoup plus facile de modifier une seule section. Lorsque vous utilisez gridpour tout, faire un petit changement peut vous obliger à changer une douzaine de lignes de code où vous devez ajuster les numéros de lignes et de colonnes, et les étendues de lignes et de colonnes pour tout juste pour accueillir un seul nouveau widget.
Regrouper le code de mise en page
Je vous recommande également de regrouper vos appels vers gridet packensemble plutôt que de les saupoudrer dans tout le code. Je trouve qu'il est beaucoup plus facile de visualiser la mise en page et d'apporter des modifications, car toutes les modifications associées sont proches les unes des autres plutôt que réparties.
Divisez l'interface utilisateur en sections logiques
Vous avez clairement trois zones distinctes: un titre en haut, des boutons à gauche et tout le reste. Alors, commencez par créer juste cela. packest sans doute le meilleur choix lorsque vous disposez d'objets disposés le long des côtés d'un espace.
Alors, commencez par créer des cadres pour ces trois domaines. Vous pouvez ensuite les packaligner le long des bords selon votre description.
db_ini_frame_top = tk.Frame(master=window, ...)
db_ini_frame_left = tk.Frame(master=window, ...)
db_ini_main = tk.Frame(master=window, ...)
db_ini_frame_top.pack(side="top", fill="x")
db_ini_frame_left.pack(side="left", fill="y")
db_ini_main.pack(side="top", fill="both", expand=True)
Placez d'autres widgets dans ces conteneurs
Même si vous avez créé un cadre en haut, vous avez mis l'étiquette et la date dans la fenêtre racine. Vous devriez les placer à l'intérieur du cadre. Lorsque vous arrivez à ajouter des boutons, ils doivent être placés dans le cadre gauche. Et enfin, pour les quatre autres fenêtres, elles doivent aller dans le troisième cadre.
db_ini_label_top = tk.Label(master=db_ini_frame_top, ...)
db_ini_date = tk.Label(master=db_ini_frame_top, ...)
db_ini_frame_center_nw = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_sw = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_ne = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_se = tk.Frame(master=db_ini_main, ...)
À utiliser gridpour les quatre cadres qui sont réellement dans une grille
Lors de l'utilisation grid, une règle de base est que vous devez attribuer un poids à au moins une ligne et une colonne afin que vous gridsachiez quoi faire avec de l'espace supplémentaire lorsque la fenêtre grandit ou rétrécit. Dans votre cas, vous voulez que les quatre cellules soient égales, vous devez donc leur donner à toutes un poids égal.
Étant donné que vous n'utilisez désormais la grille que pour ces quatre fenêtres au lieu d'essayer de tout forcer dans une seule grille, vous pouvez utiliser des numéros de ligne et de colonne qui ont du sens (c'est-à-dire: lignes 0 et 1, colonnes 0 et 1, au lieu de lignes artificiellement grandes et colonnes et travées).
db_ini_frame_center_nw = tk.Frame(master=db_ini_main,height=350,width=640,bg="blue")
db_ini_frame_center_sw = tk.Frame(master=db_ini_main,height=450,width=640,bg="light blue")
db_ini_frame_center_ne = tk.Frame(master=db_ini_main,height=350,width=640,bg="light blue")
db_ini_frame_center_se = tk.Frame(master=db_ini_main,height=450,width=640,bg="blue")
db_ini_main.grid_rowconfigure((0,1), weight=1)
db_ini_main.grid_columnconfigure((0,1), weight=1)
db_ini_frame_center_nw.grid(row=0,column=0, sticky="nsew")
db_ini_frame_center_sw.grid(row=0,column=1, sticky="nsew")
db_ini_frame_center_ne.grid(row=1,column=0, sticky="nsew")
db_ini_frame_center_se.grid(row=1,column=1, sticky="nsew")
Voici à quoi ressemble votre code complet. Je n'ai pas ajusté l'emplacement du texte dans la zone de titre, mais il est facile de le modifier sans affecter les autres zones de l'interface graphique.
Notez également que vous pouvez redimensionner manuellement la fenêtre et que tout se développe ou rétrécit de manière appropriée plutôt que de laisser des espaces vides.
import datetime
import tkinter as tk
from time import strftime
window = tk.Tk()
window.geometry("1400x800")
window.configure(bg="white")
window.rowconfigure(20,weight=1)
window.columnconfigure(35,weight=1)
window.title("Hello World App")
entry_var_server = tk.StringVar(window,"")
entry_var_db = tk.StringVar(window,"")
entry_var_driver = tk.StringVar(window,"")
def window_widgets():
db_ini_frame_top = tk.Frame(master=window,bg="#57b956",height=120,width=1400,highlightbackground="black",highlightthickness=2)
db_ini_frame_left = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_main = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_frame_top.pack(side="top", fill="x")
db_ini_frame_left.pack(side="left", fill="y")
db_ini_main.pack(side="top", fill="both", expand=True)
db_ini_label_top = tk.Label(master=db_ini_frame_top,text="Hello World",bg="#57b956")
db_ini_label_top.configure(font=("Calibri",26))
db_ini_label_top.grid(row=1,column=18,sticky="n")
def cur_date(dic = {'01':'st','21':'st','31':'st',
'02':'nd','22':'nd',
'03':'rd','23':'rd'}):
x = strftime('%A, %B %d')
return x + dic.get(x[-2:],'th')+strftime(" %G - %H:%M")
date = cur_date()
db_ini_date = tk.Label(master=db_ini_frame_top,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,sticky="w")
db_ini_frame_center_nw = tk.Frame(master=db_ini_main,height=350,width=640,bg="blue")
db_ini_frame_center_sw = tk.Frame(master=db_ini_main,height=450,width=640,bg="light blue")
db_ini_frame_center_ne = tk.Frame(master=db_ini_main,height=350,width=640,bg="light blue")
db_ini_frame_center_se = tk.Frame(master=db_ini_main,height=450,width=640,bg="blue")
db_ini_main.grid_rowconfigure((0,1), weight=1)
db_ini_main.grid_columnconfigure((0,1), weight=1)
db_ini_frame_center_nw.grid(row=0,column=0, sticky="nsew")
db_ini_frame_center_sw.grid(row=0,column=1, sticky="nsew")
db_ini_frame_center_ne.grid(row=1,column=0, sticky="nsew")
db_ini_frame_center_se.grid(row=1,column=1, sticky="nsew")
window_widgets()
window.tk.mainloop()
Le champ de date se trouve dans une seule colonne, il pousse donc la colonne suivante vers la droite.
Mettez à jour votre bloc de dates et ajoutez columnspan=4
date = cur_date()
db_ini_date = tk.Label(master=window,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,columnspan=4,sticky="w") # Allow 4 columns for date
Production