2015-12-14 9 views
9

Mein gui layouttkinter gui Layoutrahmen und Raster mit

gui layout

sieht fast nichts, wie what I expect

what I expect

so gehe ich davon gibt es einige Grundlagen, die ich nicht verstehe.

Ich nahm an, dass Rahmen ihren eigenen "Gitterraum" (Reihe, Spalte) enthalten, aber das Verhalten, das ich sehe, trägt das nicht aus, und ich bin ratlos dafür, die Dinge so zu funktionieren, wie ich es möchte Rahmen. Meine Labels sollen sich in der gleichen Zeile von L bis R befinden, unter einer "Frame-Bezeichnung", die den gesamten Frame umfasst - außer sie nicht. Ich möchte, dass die tatsächliche mehr wie das Ziel jpg aussehen, und ich möchte Raster verwenden, um es zu tun.

Sie können nur eines der Eingabefelder rechts neben dem grünen Rahmen sehen. Warum geht es dort hin?

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() 

So speziell, wo haben meine Etiketten und Entry-Widgets gehen, und wie bekomme ich sie mehr schauen, wie das Ziel (Top-Rahmen, der Rest sind für später).

+0

wenn etwas die gleiche Farbschema, wenn die beiden Bilder helfen würde verwendet, es sei denn, sie sind, und Sie sagen, dass das blaue Fenster wirklich auch auf dem Boden sein sollte obwohl der Code es auf der linken Seite platziert. –

Antwort

14

ich davon ausgegangen, dass Rahmen ihre eigenen 'Gitterraum' enthalten

Das heißt eine korrekte Annahme.

Sie können nur eines der Eingabefelder rechts vom grünen Rahmen sehen. Warum geht es dort hin?

Das Problem beginnt hier:

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

In Python, x = y().z() gesetzt immer x auf das Ergebnis der .z(). Bei top_frame = Frame(...).grid(...), grid(...) wird immer None zurückgegeben, also top_frame wird None sein. Das bewirkt, dass jedes Widget, von dem Sie denken, dass es in den obersten Frame geht, tatsächlich in das Root-Fenster gelangt.

Lösung im Überblick

Als Faustregel sollte man nie Anruf grid, pack oder place als Teil derselben Anweisung, die das Widget erstellt. Teilweise ist es für genau dieses Verhalten, das Sie erleben, aber auch, weil ich denke, dass es Ihren Code schwieriger zu schreiben macht und im Laufe der Zeit schwieriger zu pflegen ist.

Widget-Erstellung und Widget-Layout sind zwei verschiedene Dinge.Nach meiner Erfahrung sind Layoutprobleme erheblich einfacher zu debuggen, wenn Sie Ihre Layout-Befehle zusammen gruppieren.

Außerdem sollten Sie bei der Verwendung von Raster konsistent sein und die Optionen immer in der gleichen Reihenfolge platzieren, damit Sie das Layout leichter visualisieren können. Und schließlich, wenn Sie grid verwenden, sollten Sie sich angewöhnen, immer die Option sticky anzugeben, und geben Sie immer eine Zeile und eine Spalte in jedem enthaltenden Rahmen ein Nicht-Null-Gewicht.

Lösung Beispiel

Hier ist, wie ich Ihren Code schreiben würde. Es ist viel länger, aber viel einfacher zu verstehen.

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() 

Ergebnis:

screenshot of running example

+0

wahoo - vielen, vielen dank. Ich werde das sorgfältig prüfen. Ich stimme dem Farbschema-Kommentar zu, ich habe nicht genau genug darauf geachtet. – shawn

2

variable = Widget(...).grid() ordnet None zu variabel, da grid()/pack()/place() Rückkehr None

Verwendung

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