簡體   English   中英

Python 2.7 / Tkinter多個框架和菜單

[英]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()

總覽

您犯了三個常見錯誤:

  1. 您不是在要求小部件填充為其分配的空間
  2. 你不是在告訴tkinter如何分配額外的空間
  3. 您正在關閉幾何傳播

使小部件填充其分配的空間

第一個問題可以通過在調用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_propagatepack_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")

請注意,在創建leftframerightframebottomframe時,我還如何顯式設置父bottomframe 沒有理由不這樣做,這使代碼更具自記錄性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM