【问题标题】:How can I align elements across different frames in tkinter?如何在 tkinter 中跨不同帧对齐元素?
【发布时间】:2020-03-26 13:11:01
【问题描述】:

我正在重新组织 GUI 的结构,但我遇到了一些对齐问题。我在左侧有一个LabelFrame,其中包含一个matplotlib 画布,右侧有一个Notebook,在选项卡中包含多个LabelFrames,每个选项卡都包含另一个matplotlib 画布。我想在视觉上将Notebook 中的内部LabelFrames 与最左边的LabelFrame 对齐,这样在下图中,“左框架”和下方的“Tab 1”字样是垂直对齐的。怎么可能呢?下面包括一个(大部分)最小的工作示例。

import tkinter as tk
from tkinter import ttk
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk

class App(tk.Frame):
    def __init__(self,parent):
        tk.Frame.__init__(self, parent)
        parent.deiconify()
        self.parent = parent

        #define and position the main panel on the left
        self.left_frame = tk.LabelFrame(self.parent, text='Left Panel')
        self.left_frame.grid(row=0,column=0)

        #define and position the tab-enabled secondary panel on the right
        self.ntbk = ttk.Notebook(self.parent)
        self.ntbk.grid(row=0,column=1)

        #define internal frames for the tabs
        self.tab1_frame = tk.LabelFrame(self.ntbk, text='Tab 1')
        self.tab2_frame = tk.LabelFrame(self.ntbk, text='Tab 2')

        self.ntbk.add(self.tab1_frame, text='Tab 1')
        self.ntbk.add(self.tab2_frame, text='Tab 2')


        #Left panel children
        #define a figure canvas to go in the left panel
        self.left_f = Figure(figsize=(7,5), dpi=100)
        self.left_canvas = FigureCanvasTkAgg(self.left_f, master=self.left_frame)
        self.left_toolbar_frame = tk.Frame(self.left_frame)
        self.left_toolbar = NavigationToolbar2Tk(self.left_canvas, self.left_toolbar_frame)
        self.left_toolbar.update()
        self.left_canvas.get_tk_widget().grid(row=0,column=0)
        self.left_toolbar_frame.grid(row=1,column=0)

        #define a control panel for the left panel to go below the figure
        self.left_control_frame = tk.LabelFrame(self.left_frame, text='Left Control Panel')
        self.left_control_frame.grid(row=2,column=0, sticky=tk.E+tk.W)

        self.left_button = tk.Button(self.left_control_frame, text='Button')
        self.left_button.grid(row=0,column=0, sticky=tk.E+tk.W)


        #notebook children
        #define a figure canvas to go in tab 1
        self.tab1_f = Figure(figsize=(7,5), dpi=100)
        self.tab1_canvas = FigureCanvasTkAgg(self.tab1_f, master=self.tab1_frame)
        self.tab1_toolbar_frame = tk.Frame(self.tab1_frame)
        self.tab1_toolbar = NavigationToolbar2Tk(self.tab1_canvas, self.tab1_toolbar_frame)
        self.tab1_toolbar.update()
        self.tab1_canvas.get_tk_widget().grid(row=0,column=0)
        self.tab1_toolbar_frame.grid(row=1,column=0)

        self.tab1_control_frame = tk.LabelFrame(self.tab1_frame, text='Tab 1 Control Panel')
        self.tab1_control_frame.grid(row=2,column=0, sticky=tk.E+tk.W)

        self.tab1_button = tk.Button(self.tab1_control_frame, text='Button')
        self.tab1_button.grid(row=0,column=0, sticky=tk.E+tk.W)

        #define a figure canvas to go in tab 2
        self.tab2_f = Figure(figsize=(7,5), dpi=100)
        self.tab2_canvas = FigureCanvasTkAgg(self.tab2_f, master=self.tab2_frame)
        self.tab2_toolbar_frame = tk.Frame(self.tab2_frame)
        self.tab2_toolbar = NavigationToolbar2Tk(self.tab2_canvas, self.tab2_toolbar_frame)
        self.tab2_toolbar.update()
        self.tab2_canvas.get_tk_widget().grid(row=0,column=0)
        self.tab2_toolbar_frame.grid(row=1,column=0)

        self.tab2_control_frame = tk.LabelFrame(self.tab2_frame, text='Tab 2 Control Panel')
        self.tab2_control_frame.grid(row=2,column=0, sticky=tk.E+tk.W)

        self.tab2_button = tk.Button(self.tab2_control_frame, text='Button')
        self.tab2_button.grid(row=0,column=0, sticky=tk.E+tk.W)



def main():
    root=tk.Tk()
    root.withdraw()
    App(root).grid(row=0,column=0)
    root.mainloop()

if __name__=="__main__":
    main()

【问题讨论】:

    标签: python-3.x tkinter tkinter-layout


    【解决方案1】:

    如果只希望它在视觉上对齐,只需在代码中添加一些填充。

    在您的 LeftFrame .grid() 中,添加 pady=xx 并手动查看外观。

    self.left_frame.grid(row=0,column=0,pady=(22,0)) # This will be bad when you use DPI awareness.
    

    PS:我尝试用self.ntbk.winfo_height()-self.tab1_frame.winfo_height()得到tab的高度,但实际上并不准确。(它得到28,但看起来不是很好。)

    编辑:我找到了直接设置Tab1y的方法,现在你的代码可能是:

    import tkinter as tk
    from tkinter import ttk
    import matplotlib
    matplotlib.use('TkAgg')
    from matplotlib.figure import Figure
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
    # import ctypes,sys 
    #
    # if sys.getwindowsversion().major == 10:
    #     ctypes.windll.shcore.SetProcessDpiAwareness(2) # DPI AWARENESS
    
    
    class App(tk.Frame):
        def getTabHeight(self):
            self.left_frame.grid(row=0,column=0,pady=(self.tab1_frame.winfo_y()-2,0))  # Get its height,I don't know why it need to minus 2,But in this way,no matter you use DPI awareness,It looked good.
    
        def __init__(self,parent):
            tk.Frame.__init__(self, parent)
            parent.deiconify()
            self.parent = parent
    
            #define and position the main panel on the left
            self.left_frame = tk.LabelFrame(self.parent, text='Left Panel')
    
            #define and position the tab-enabled secondary panel on the right
            self.ntbk = ttk.Notebook(self.parent)
            self.ntbk.grid(row=0,column=1)
    
            #define internal frames for the tabs
            self.tab1_frame = tk.LabelFrame(self.ntbk, text='Tab 1')
            self.tab2_frame = tk.LabelFrame(self.ntbk, text='Tab 2')
    
            self.ntbk.add(self.tab1_frame, text='Tab 1')
            self.ntbk.add(self.tab2_frame, text='Tab 2')
    
    
            #Left panel children
            #define a figure canvas to go in the left panel
            self.left_f = Figure(figsize=(7,5), dpi=100)
            self.left_canvas = FigureCanvasTkAgg(self.left_f, master=self.left_frame)
            self.left_toolbar_frame = tk.Frame(self.left_frame)
            self.left_toolbar = NavigationToolbar2Tk(self.left_canvas, self.left_toolbar_frame)
            self.left_toolbar.update()
            self.left_canvas.get_tk_widget().grid(row=0,column=0)
            self.left_toolbar_frame.grid(row=1,column=0)
    
            #define a control panel for the left panel to go below the figure
            self.left_control_frame = tk.LabelFrame(self.left_frame, text='Left Control Panel')
            self.left_control_frame.grid(row=2,column=0, sticky=tk.E+tk.W)
    
            self.left_button = tk.Button(self.left_control_frame, text='Button')
            self.left_button.grid(row=0,column=0, sticky=tk.E+tk.W)
    
    
            #notebook children
            #define a figure canvas to go in tab 1
            self.tab1_f = Figure(figsize=(7,5), dpi=100)
            self.tab1_canvas = FigureCanvasTkAgg(self.tab1_f, master=self.tab1_frame)
            self.tab1_toolbar_frame = tk.Frame(self.tab1_frame)
            self.tab1_toolbar = NavigationToolbar2Tk(self.tab1_canvas, self.tab1_toolbar_frame)
            self.tab1_toolbar.update()
            self.tab1_canvas.get_tk_widget().grid(row=0,column=0)
            self.tab1_toolbar_frame.grid(row=1,column=0)
    
            self.tab1_control_frame = tk.LabelFrame(self.tab1_frame, text='Tab 1 Control Panel')
            self.tab1_control_frame.grid(row=2,column=0, sticky=tk.E+tk.W)
    
            self.tab1_button = tk.Button(self.tab1_control_frame, text='Button')
            self.tab1_button.grid(row=0,column=0, sticky=tk.E+tk.W)
    
            #define a figure canvas to go in tab 2
            self.tab2_f = Figure(figsize=(7,5), dpi=100)
            self.tab2_canvas = FigureCanvasTkAgg(self.tab2_f, master=self.tab2_frame)
            self.tab2_toolbar_frame = tk.Frame(self.tab2_frame)
            self.tab2_toolbar = NavigationToolbar2Tk(self.tab2_canvas, self.tab2_toolbar_frame)
            self.tab2_toolbar.update()
            self.tab2_canvas.get_tk_widget().grid(row=0,column=0)
            self.tab2_toolbar_frame.grid(row=1,column=0)
    
            self.tab2_control_frame = tk.LabelFrame(self.tab2_frame, text='Tab 2 Control Panel')
            self.tab2_control_frame.grid(row=2,column=0, sticky=tk.E+tk.W)
    
            self.tab2_button = tk.Button(self.tab2_control_frame, text='Button')
            self.tab2_button.grid(row=0,column=0, sticky=tk.E+tk.W)
    
            self.after(100,self.getTabHeight)
    
    
    
    def main():
        root=tk.Tk()
        root.withdraw()
        App(root).grid(row=0,column=0)
        root.mainloop()
    
    if __name__=="__main__":
        main()
    

    在 DPI 感知方面:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-25
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      • 2015-07-15
      • 1970-01-01
      相关资源
      最近更新 更多