Tkinter Grid Problem - Frames nicht ausgerichtet
Ich habe gerade angefangen mit tkinter zu arbeiten und versuche mich immer noch daran zu gewöhnen, wie es funktioniert. Ich habe versucht, eine Art Rastermenü mit 4 Abschnitten vorzubereiten.
Oben befindet sich ein Frame mit dem Titel der App, links ein Frame mit einigen Schaltflächen zum Konfigurieren der App und im Rest 4 gleich große Frames.
Mein Hauptproblem hier ist die leere Spalte zwischen dem linken Rahmen und den anderen vier. Wie kann ich dies anpassen, damit die 4 Quadrate diesen Raum ausfüllen?
Siehe unter dem 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()
Antworten
Während wir Ihren Code mit nur ein paar kleinen Änderungen reparieren können, wird es viel einfacher sein, Ihren Code zu ändern, wenn die Anwendung wächst, wenn Sie sich ein paar Minuten Zeit nehmen, um ein intelligenteres Layout zu erstellen.
Ich werde einige Ratschläge geben, wie ich Ihren Code neu organisieren würde. Am Ende der Antwort steht ein letztes Arbeitsbeispiel. 90% davon sind Ihr Originalcode, aber mit ein paar Änderungen hier und da, um die Erstellung der Benutzeroberfläche zu vereinfachen.
Nicht gridfür alles verwenden
Zunächst empfehle ich , dass Sie nicht verwenden , gridfür alles. Es ist gut zum Erstellen von Rastern, aber es gibt manchmal bessere Möglichkeiten, ein ganzes Fenster auszulegen. Teilen Sie Ihre Benutzeroberfläche in logische Gruppierungen ein und legen Sie sie dann mithilfe dieser Gruppierungen an.
Durch die Organisation Ihrer Benutzeroberfläche in Abschnitte wird es viel einfacher, nur einen einzelnen Abschnitt zu ändern. Wenn Sie gridfür alles verwenden, müssen Sie für eine kleine Änderung möglicherweise ein Dutzend Codezeilen ändern, in denen Sie die Zeilen- und Spaltennummern sowie die Zeilen- und Spaltenbereiche für alles anpassen müssen, um nur ein einziges neues Widget aufzunehmen.
Gruppieren Sie den Layoutcode
Ich empfehle außerdem, dass Sie Ihre Anrufe zu gridund packzusammen gruppieren, anstatt sie im gesamten Code zu verteilen. Ich finde, es macht es viel einfacher, das Layout zu visualisieren und Änderungen vorzunehmen, da alle damit verbundenen Änderungen nahe beieinander liegen und nicht verteilt sind.
Teilen Sie die Benutzeroberfläche in logische Abschnitte
Sie haben eindeutig drei unterschiedliche Bereiche: einen Titel oben, einige Schaltflächen links und dann alles andere. Beginnen Sie also damit, genau das zu erstellen. packist wohl die beste Wahl, wenn Sie Dinge entlang der Seiten eines Raumes angeordnet haben.
Beginnen Sie also damit, Rahmen für diese drei Bereiche zu erstellen. Sie können sie dann verwenden pack, um sie gemäß Ihrer Beschreibung entlang der Kanten auszurichten.
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)
Platzieren Sie andere Widgets in diesen Containern
Obwohl Sie oben einen Rahmen erstellt haben, haben Sie die Beschriftung und das Datum in das Stammfenster eingefügt. Sie sollten sie innerhalb des Rahmens platzieren. Wenn Sie zum Hinzufügen von Schaltflächen kommen, sollten diese im linken Rahmen angezeigt werden. Und schließlich müssen die anderen vier Fenster in den dritten Frame gehen.
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, ...)
Verwenden Sie diese Option gridfür die vier Frames, die sich tatsächlich in einem Raster befinden
Als gridFaustregel gilt, dass Sie mindestens einer Zeile und einer Spalte ein Gewicht geben sollten, damit Sie gridwissen, was Sie mit zusätzlichem Platz tun müssen, wenn das Fenster wächst oder schrumpft. In Ihrem Fall möchten Sie, dass alle vier Zellen gleich sind, also sollten Sie allen das gleiche Gewicht geben.
Da Sie jetzt das Raster nur für diese vier Fenster verwenden, anstatt zu versuchen, alles in ein einziges Raster zu zwingen, können Sie sinnvolle Zeilen- und Spaltennummern verwenden (z. B. Zeilen 0 und 1, Spalten 0 und 1 anstelle von künstlich großen Zeilen und Spalten und Spannweiten).
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")
So sieht Ihr vollständiger Code aus. Ich habe die Position des Textes im Titelbereich nicht angepasst, aber es ist einfach, ihn zu ändern, ohne die anderen Bereiche der GUI zu beeinflussen.
Beachten Sie außerdem, dass Sie die Fenstergröße manuell ändern können und alles entsprechend wächst oder schrumpft, anstatt leere Stellen zu hinterlassen.
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()
Das Datumsfeld befindet sich in einer einzelnen Spalte, sodass die nächste Spalte nach rechts verschoben wird.
Aktualisieren Sie Ihren Datumsblock und fügen Sie ihn hinzu 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
Ausgabe