简体   繁体   English

tkinter:框架和网格

[英]tkinter: Frame and grid

I, for the life of me, cannot understand how to use grid() to manage widgets inside a Frame ( Python 3.6 ). 我一生都无法理解如何使用grid()管理FramePython 3.6 )中的小部件。 The code below tries to show a 2-by-2 matrix of ListBox es in the root window. 下面的代码尝试在根窗口中显示ListBox的2×2矩阵。

    import tkinter as TK

    root = TK.Tk()
    root.title('My App')
    rootWidth = 768
    rootHeight = 768
    root.geometry('{}x{}+0+0'.format(rootWidth, rootHeight))
    root.resizable(width=False, height=False)

    frame00 = TK.Frame(root, bd=2, relief=TK.SUNKEN)
    box00 = TK.Listbox(frame00, bd=0)
    box10 = TK.Listbox(frame00, bd=0)

    box00.grid(row=0, sticky=TK.N)
    box10.grid(row=1, sticky=TK.S)
    frame00.grid(row=0, column=0, sticky=TK.W)
    frame00.rowconfigure(0, weight=1)
    frame00.rowconfigure(1, weight=1)


    frame01 = TK.Frame(root, bd=2, relief=TK.SUNKEN)
    box01 = TK.Listbox(frame01, bd=0)
    box11 = TK.Listbox(frame01, bd=0)

    box01.grid(row=0, sticky=TK.N)
    box11.grid(row=1, sticky=TK.S)
    frame01.grid(row=0, column=1, sticky=TK.E)
    frame01.rowconfigure(0, weight=1)
    frame01.rowconfigure(1, weight=2)

    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(0, weight=1)
    root.grid_columnconfigure(1, weight=1)

    for i in range(20):
        box00.insert(TK.END, 'test')
        box10.insert(TK.END, 'test')
        box01.insert(TK.END, 'test')
        box11.insert(TK.END, 'test')

In the end, I only see two ListBoxes (ie, only one row) instead of 4 of them in my GUI. 最后,我在GUI中仅看到两个ListBoxes (即只有一行),而不是其中的4个。 But, If I use one Frame per ListBox , then everything works. 但是,如果每个ListBox使用一Frame ,则一切正常。

    import tkinter as TK

    root = TK.Tk()
    root.title('My App')
    rootWidth = 768
    rootHeight = 768
    root.geometry('{}x{}+0+0'.format(rootWidth, rootHeight))
    root.resizable(width=False, height=False)

    frame00 = TK.Frame(root, bd=2, relief=TK.SUNKEN)
    box00 = TK.Listbox(frame00, bd=0)
    frame10 = TK.Frame(root, bd=2, relief=TK.RAISED)
    box10 = TK.Listbox(frame10, bd=0)

    box00.grid(row=0, sticky=TK.N)
    box10.grid(row=0, sticky=TK.S)
    frame00.grid(row=0, column=0, sticky=TK.W)
    frame10.grid(row=1, column=0, sticky=TK.W)


    frame01 = TK.Frame(root, bd=2, relief=TK.SUNKEN)
    box01 = TK.Listbox(frame01, bd=0)
    frame11 = TK.Frame(root, bd=2, relief=TK.RAISED)
    box11 = TK.Listbox(frame11, bd=0)

    box01.grid(row=0, sticky=TK.N)
    box11.grid(row=0, sticky=TK.S)
    frame01.grid(row=0, column=1, sticky=TK.E)
    frame11.grid(row=1, column=1, sticky=TK.E)

    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(0, weight=1)
    root.grid_columnconfigure(1, weight=1)

    for i in range(20):
        box00.insert(TK.END, 'test')
        box10.insert(TK.END, 'test')
        box01.insert(TK.END, 'test')
        box11.insert(TK.END, 'test')

Is it that inside Frame, you can only use pack() ? 是在Frame内部,您只能使用pack()吗?

UPDATE UPDATE

People in the thread pointed out that in the original code list I didn't use the column keyword argument in those grid() calls. 线程中的人指出,在原始代码列表中,我没有在那些grid()调用中使用column关键字参数。 In fact, I did, it is just that I remove them in my latest try before posting which basically resulted in the same. 实际上,我确实做到了,只是我在发布前的最新尝试中将其删除了,基本上导致了相同的结果。

Here is a new version that includes the column arguments, which shows only two ListBox es, too. 这是一个包含column参数的新版本,该参数也仅显示两个ListBox

root = TK.Tk()
root.title('Script Launcher')
rootWidth = 768
rootHeight = 768
root.geometry('{}x{}+0+0'.format(rootWidth, rootHeight))
root.resizable(width=False, height=False)

frame00 = TK.Frame(root, bd=2, relief=TK.SUNKEN)
box00 = TK.Listbox(frame00, bd=0)
box10 = TK.Listbox(frame00, bd=0)

box00.grid(row=0, column=0, sticky=TK.N)
box10.grid(row=1, column=0, sticky=TK.S)
frame00.grid(row=0, column=0, sticky=TK.W)
frame00.rowconfigure(0, weight=1)
frame00.rowconfigure(1, weight=1)
frame00.columnconfigure(0, weight=1)


frame01 = TK.Frame(root, bd=2, relief=TK.SUNKEN)
box01 = TK.Listbox(frame01, bd=0)
box11 = TK.Listbox(frame01, bd=0)

box01.grid(row=0, column=1,  sticky=TK.N)
box11.grid(row=1, column=1, sticky=TK.S)
frame01.grid(row=0, column=1, sticky=TK.E)
frame01.rowconfigure(0, weight=1)
frame01.rowconfigure(1, weight=1)
frame01.columnconfigure(0, weight=1)

root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)

for name in range(20)
    box00.insert(TK.END, 'test')
    box10.insert(TK.END, 'test')
    box01.insert(TK.END, 'test')
    box11.insert(TK.END, 'test')


root.mainloop()

The grid() method tells the GridManager how to handle the widget that is calling grid(). grid()方法告诉GridManager如何处理正在调用grid()的小部件。 So if you called Tk().grid(), that would be pointless yes. 因此,如果调用Tk()。grid(),那将毫无意义。 I prefer to have a class like MyApp as the base level "wrapper" for all internal widgets. 我更喜欢将MyApp之类的类作为所有内部小部件的基本级别“包装器”。

Rewrote on my system, this produces a GUI in the form of: 在我的系统上重写后,将产生以下形式的GUI:

-----------------------------------
|                |                |
|                |                |
|    ListBox     |     ListBox    |
|                |                |
|                |                |
-----------------------------------
|                |                |
|                |                |
|    ListBox     |     ListBox    |
|                |                |
|                |                |
-----------------------------------

The outer level is the TK.Tk() , its first inner level is a TK.Frame() . 外层是TK.Tk() ,它的第一个内层是TK.Frame() Then that is broken into left and right, each a TK.Frame() . 然后将其分为左右两个,每个都是TK.Frame() Looks like: 看起来像:

-----------------------------------
|                |                |
|                |                |
|                |                |
|                |                |
|                |                |
|     Frame      |      Frame     |
|                |                |
|                |                |
|                |                |
|                |                |
|                |                |
-----------------------------------

Then we grid each internal frame vertically by setting the weights of the rows. 然后,通过设置行的权重,垂直将每个内部框架网格化。

import tkinter as TK

class MyApp(TK.Frame):

    def __init__(self, master):
        super().__init__(master) # initialize the 'TK.Frame'

        # configure the root Frame (i.e. 'self')
        self.master = master # just for reference later
        self.master.grid_rowconfigure(0, weight = 1)
        self.master.grid_columnconfigure(0, weight = 1)
        self.grid(column = 0, row = 0, sticky = 'nsew')
        self.grid_rowconfigure(0, weight = 1)
        self.grid_columnconfigure(0, weight = 1) # columns will split space
        self.grid_columnconfigure(1, weight = 1) # columns will split space

        # configure internal left Frame
        self.left_frame = TK.Frame(self, borderwidth = 2, relief = TK.SUNKEN)
        self.left_frame.grid_rowconfigure(0, weight = 1) # rows will split space
        self.left_frame.grid_rowconfigure(1, weight = 1) # rows will split space
        self.left_frame.grid_columnconfigure(0, weight = 1)
        self.left_frame.grid(column = 0, row = 0, sticky = 'nsew')
        self.left_box0 = TK.Listbox(self.left_frame, borderwidth = 0)
        self.left_box0.grid(column = 0, row = 0, sticky = 'nsew')
        self.left_box1 = TK.Listbox(self.left_frame, borderwidth = 0)
        self.left_box1.grid(column = 0, row = 1, sticky = 'nsew')

        # configure internal right Frame
        self.right_frame = TK.Frame(self, borderwidth = 2, relief = TK.SUNKEN)
        self.right_frame.grid_rowconfigure(0, weight = 1) # rows will split space
        self.right_frame.grid_rowconfigure(1, weight = 1) # rows will split space
        self.right_frame.grid_columnconfigure(0, weight = 1)
        self.right_frame.grid(column = 1, row = 0, sticky = 'nsew')
        self.right_box0 = TK.Listbox(self.right_frame, borderwidth = 0)
        self.right_box0.grid(column = 0, row = 0, sticky = 'nsew')
        self.right_box1 = TK.Listbox(self.right_frame, borderwidth = 0)
        self.right_box1.grid(column = 0, row = 1, sticky = 'nsew')

        for i in range(20):
            self.left_box0.insert(TK.END, 'test')
            self.left_box1.insert(TK.END, 'test')
            self.right_box0.insert(TK.END, 'test')
            self.right_box1.insert(TK.END, 'test')


if __name__ == '__main__': # get in the habit of doing this
    root = TK.Tk()
    root.title('My App')
    root.geometry('{}x{}'.format(768, 768))
    root.resizable(width = False, height = False)
    app = MyApp(root)
    app.mainloop()

You forget to add column to the grid see this example to do it. 您忘记将column添加到grid请参见此示例。

box00.grid(row=0, column=45, sticky=TK.N)

grid works like excel sheet with rows and column grid工作原理类似于具有rowscolumn Excel工作表

check this link to read more about it. 检查此链接以了解更多信息。 it is well documented there. 那里有很好的记录。

FULL CODE 完整代码

import tkinter as TK

root = TK.Tk()
root.title('My App')
rootWidth = 768
rootHeight = 768
root.geometry('{}x{}+0+0'.format(rootWidth, rootHeight))
root.resizable(width=False, height=False)

frame00 = TK.Frame(root, bd=2, relief=TK.SUNKEN)
box00 = TK.Listbox(frame00, bd=0)
box10 = TK.Listbox(frame00, bd=0)

box00.grid(row=0, column=75, sticky=TK.N)
box10.grid(row=1, column=5, sticky=TK.S)
frame00.grid(row=0, column=0, sticky=TK.W)
frame00.rowconfigure(0, weight=1)
frame00.rowconfigure(1, weight=1)

frame01 = TK.Frame(root, bd=2, relief=TK.SUNKEN)
box01 = TK.Listbox(frame01, bd=0)
box11 = TK.Listbox(frame01, bd=0)

box01.grid(row=0, column=7, sticky=TK.N)
box11.grid(row=1, column=60,  sticky=TK.S)
frame01.grid(row=0, column=1, sticky=TK.E)
frame01.rowconfigure(0, weight=1)
frame01.rowconfigure(1, weight=2)

root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)

for i in range(20):
    box00.insert(TK.END, 'test')
    box10.insert(TK.END, 'test')
    box01.insert(TK.END, 'test')
    box11.insert(TK.END, 'test')

root.mainloop()

You can use grid() inside Frame. 您可以在Frame内部使用grid()。 Here is an example. 这是一个例子。 Hope it helps... 希望能帮助到你...

    import tkinter as tk
    from tkinter import *
    from tkinter import ttk

    class GUI:

        def __init__(self, master):
            mainframe = ttk.Frame(master)
            mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
            mainframe.columnconfigure(0, weight=1)
            mainframe.rowconfigure(0, weight=1)
            list1 = Listbox(master, bd=0)
            list1.grid(column=0, row=0)
            list2 = Listbox(master, bd=0)
            list2.grid(column=1, row=0)
            separator1 = Frame(list1, height=2, bd=1, relief=SUNKEN)
            separator1.grid(column=0, row=0)
            separator2 = Frame(list1, height=2, bd=1, relief=SUNKEN)
            separator2.grid(column=1, row=0)
            separator3 = Frame(list2, height=2, bd=1, relief=SUNKEN)
            separator3.grid(column=2, row=0)
            separator4 = Frame(list2, height=2, bd=1, relief=SUNKEN)
            separator4.grid(column=3, row=0)
            e1 = Label(separator1, text='Label1')
            e1.grid(sticky=W+E)
            e2= Label(separator2, text='Label2')
            e2.grid(sticky=W+E)
            e3 = Label(separator3, text='Label3')
            e3.grid(sticky=W+E)
            e4= Label(separator4, text='Label4')
            e4.grid(sticky=W+E)    

    root = Tk()
    my_gui = GUI(root)
    root.mainloop()

Here's a very nice explanation for tkinter http://effbot.org/tkinterbook/grid.htm 这是tkinter的一个很好的解释http://effbot.org/tkinterbook/grid.htm

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM