tkinter:框架和网格
tkinter: Frame and grid
我这辈子都无法理解如何使用 grid()
来管理 Frame
(Python 3.6 中的小部件).下面的代码尝试在根 window.
中显示 ListBox
es 的 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')
最后,我在我的 GUI 中只看到两个 ListBoxes
(即只有一行)而不是 4 个。
但是,如果我对每个 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')
是不是Frame里面只能用pack()
?
更新
线程中的人指出,在原始代码列表中,我没有在那些 grid()
调用中使用 column
关键字参数。事实上,我做到了,只是我在发布前的最近一次尝试中删除了它们,结果基本上是一样的。
这是一个包含 column
参数的新版本,它也只显示两个 ListBox
es。
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()
您忘记将 column
添加到 grid
请参阅此示例。
box00.grid(row=0, column=45, sticky=TK.N)
grid
的工作方式类似于 excel sheet 与 rows
和 column
检查此 link 以阅读更多相关信息。那里有很好的记录。
完整代码
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()
您可以在 Frame 中使用 grid()。这是一个例子。希望对你有帮助...
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()
这里有一个很好的 tkinter 解释 http://effbot.org/tkinterbook/grid.htm
grid() 方法告诉 GridManager 如何处理调用 grid() 的小部件。因此,如果您调用 Tk().grid(),那将毫无意义。我更喜欢使用像 MyApp 这样的 class 作为所有内部小部件的基本级别 "wrapper"。
在我的系统上重写,生成如下形式的 GUI:
-----------------------------------
| | |
| | |
| ListBox | ListBox |
| | |
| | |
-----------------------------------
| | |
| | |
| ListBox | ListBox |
| | |
| | |
-----------------------------------
外层是TK.Tk()
,它的第一个内层是TK.Frame()
。然后就是分成左右两个,各一个TK.Frame()
。看起来像:
-----------------------------------
| | |
| | |
| | |
| | |
| | |
| Frame | Frame |
| | |
| | |
| | |
| | |
| | |
-----------------------------------
然后我们通过设置行的权重将每个内部框架垂直网格化。
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()
我这辈子都无法理解如何使用 grid()
来管理 Frame
(Python 3.6 中的小部件).下面的代码尝试在根 window.
ListBox
es 的 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')
最后,我在我的 GUI 中只看到两个 ListBoxes
(即只有一行)而不是 4 个。
但是,如果我对每个 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')
是不是Frame里面只能用pack()
?
更新
线程中的人指出,在原始代码列表中,我没有在那些 grid()
调用中使用 column
关键字参数。事实上,我做到了,只是我在发布前的最近一次尝试中删除了它们,结果基本上是一样的。
这是一个包含 column
参数的新版本,它也只显示两个 ListBox
es。
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()
您忘记将 column
添加到 grid
请参阅此示例。
box00.grid(row=0, column=45, sticky=TK.N)
grid
的工作方式类似于 excel sheet 与 rows
和 column
检查此 link 以阅读更多相关信息。那里有很好的记录。
完整代码
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()
您可以在 Frame 中使用 grid()。这是一个例子。希望对你有帮助...
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()
这里有一个很好的 tkinter 解释 http://effbot.org/tkinterbook/grid.htm
grid() 方法告诉 GridManager 如何处理调用 grid() 的小部件。因此,如果您调用 Tk().grid(),那将毫无意义。我更喜欢使用像 MyApp 这样的 class 作为所有内部小部件的基本级别 "wrapper"。
在我的系统上重写,生成如下形式的 GUI:
-----------------------------------
| | |
| | |
| ListBox | ListBox |
| | |
| | |
-----------------------------------
| | |
| | |
| ListBox | ListBox |
| | |
| | |
-----------------------------------
外层是TK.Tk()
,它的第一个内层是TK.Frame()
。然后就是分成左右两个,各一个TK.Frame()
。看起来像:
-----------------------------------
| | |
| | |
| | |
| | |
| | |
| Frame | Frame |
| | |
| | |
| | |
| | |
| | |
-----------------------------------
然后我们通过设置行的权重将每个内部框架垂直网格化。
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()