[英]Python 2.7 / Tkinter multiple frames and menu
我想制作一個管理工具,在其左側有一個菜單,在右側有更改框架。 我讀了一篇有關更改框架的教程,並嘗試從那里開始。 問題是右框架應始終為1200x750。這是行不通的。 我知道python,但仍然有一些關於面向對象的python的學習知識。有人看到我在這里丟失了嗎?
import Tkinter as tk
import tkFont as tkfont
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
self.grid_columnconfigure(1, weight=0)
self.grid_columnconfigure(2, weight=1)
self.grid_rowconfigure(1, weight=1)
leftframe = tk.Frame(self, width=300, height=750, bd=1, relief = tk.SOLID, bg="white")
rightframe = tk.Frame(self, width=1200, height=750, bd=1, relief = tk.SOLID, bg="white")
bottomframe = tk.Frame(self, width=1500, height=50, bd=1, relief = tk.SOLID, bg="white")
leftframe.grid(row=1,column=1, sticky="nsew")
rightframe.grid(row=1, column=2, sticky="nsew")
bottomframe.grid(row=2, column=1, columnspan=2, sticky="nsew")
leftframe.pack_propagate(0) # <-- still got this in to make the menu width fixed
button1 = tk.Button(leftframe, text="Start page" , anchor="w", bg="white", bd=0, command=lambda: self.show_frame("StartPage")).pack(padx=10, anchor="sw", fill="x")
button2 = tk.Button(leftframe, text="Page 1" , anchor="w", bg="white", bd=0, command=lambda: self.show_frame("PageOne")).pack(padx=10, fill="x")
button3 = tk.Button(leftframe, text="Page 2" , anchor="w", bg="white", bd=0, command=lambda: self.show_frame("PageTwo")).pack(padx=10, fill="x")
button4 = tk.Button(leftframe, text="Page 3" , anchor="w", bg="white", bd=0, command=lambda: self.show_frame("PageOne")).pack(padx=10, fill="x")
button5 = tk.Button(leftframe, text="Page 4" , anchor="w", bg="white", bd=0, command=lambda: self.show_frame("PageOne")).pack(padx=10, fill="x")
button5 = tk.Button(leftframe, text="Page 5" , anchor="w", bg="white", bd=0, command=lambda: self.show_frame("PageOne")).pack(padx=10, fill="x")
self.frames = {}
for F in (StartPage, PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=rightframe, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.config(bg="white")
frame.grid(row=0, column=0, sticky="news")
self.show_frame("StartPage")
self.init_topmenu()
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
def init_topmenu(self):
menubar = tk.Menu(self)
self.config(menu=menubar)
fileMenu = tk.Menu(menubar)
fileMenu.add_command(label="Page 1", command=lambda: self.show_frame("PageOne"))
fileMenu.add_command(label="Page 2", command=lambda: self.show_frame("PageTwo"))
menubar.add_cascade(label="File", menu=fileMenu)
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the Startpage", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 2", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
if __name__ == "__main__":
app = SampleApp()
window_width = 1500
window_height = 800
width = app.winfo_screenwidth()
height = app.winfo_screenheight()
app.geometry('%dx%d+%d+%d' % (window_width, window_height, width*0.5-(window_width/2), height*0.5-(window_height/2)))
app.mainloop()
您犯了三個常見錯誤:
第一個問題可以通過在調用grid
時使用sticky
屬性來解決。 例如:
leftframe.grid(row=1,column=1, sticky="nsew")
rightframe.grid(row=1, column=2, sticky="nsew")
bottomframe.grid(row=2, column=1, columnspan=2, sticky="nsew")
您還需要在每個頁面上執行此操作:
frame.grid(row=0, column=0, sticky="nesw")
第二個問題可以通過賦予行和列權重來解決。 Tkinter將使用行或列的weight
來確定是否應為該行或列分配剩余的空間。 這也許是人們在使用grid
時最常犯的錯誤。
根據經驗,每次使用grid
,主窗口小部件至少應具有一行和一列,且權重非零。
self.grid_columnconfigure(1, weight=0)
self.grid_columnconfigure(2, weight=1)
self.grid_rowconfigure(1, weight=1)
您正在關閉幾何圖形傳播,這很少是一個好的解決方案。 我強烈建議您刪除對grid_propagate
和pack_propagate
所有調用。 使用tkinter的最佳方法是配置內部小部件,並讓包含的小部件增大或縮小以適應。 正確設置GUI時,無論當時使用哪種分辨率或字體,它的大小都是正確的。
我使用tk或tkinter已有20多年了,在這些年中,關閉幾何圖形傳播的次數最多,非常少。 這是一個高級選項,僅對某些特定的邊緣情況有用。
這不是問題的根源,但有助於使代碼更易於理解。 我強烈建議您將小部件的創建與在屏幕上的組織分開。 當您閱讀“ widget,grid,widget,grid,widget,grid”時,很難對所構建的內容做出心理印象。 相反,如果您有“ widget,widget,widget”,然后是“ grid,grid,grid”,則可以完全清楚要構建的內容。
例如,我將重新排列代碼的開頭,使其看起來像這樣:
self.grid_columnconfigure(1, weight=0)
self.grid_columnconfigure(2, weight=1)
self.grid_rowconfigure(1, weight=1)
leftframe = tk.Frame(self, width=300, height=750, bd=1, relief = tk.SOLID, bg="white")
rightframe = tk.Frame(self, width=1200, height=750, bd=1, relief = tk.SOLID, bg="white")
bottomframe = tk.Frame(self, width=1500, height=50, bd=1, relief = tk.SOLID, bg="white")
leftframe.grid(row=1,column=1, sticky="nsew")
rightframe.grid(row=1, column=2, sticky="nsew")
bottomframe.grid(row=2, column=1, columnspan=2, sticky="nsew")
請注意,在創建leftframe
, rightframe
和bottomframe
時,我還如何顯式設置父bottomframe
。 沒有理由不這樣做,這使代碼更具自記錄性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.