Tkinter是Python标准GUI工具包,有三种布局管理方式:
- pack
- grid
- place
这三种布局管理在同一个 master window 里是不可以混用的。
下面通过三示例,详解使用参数和使用方法:
Pack布局
#!/usr/bin/env python # _*_ coding:utf-8 _*_ from tkinter import * root = Tk() Button(root,text='A').pack(side=LEFT,expand=YES,fill=Y) Button(root,text='B').pack(side=TOP,expand=YES,fill=BOTH) Button(root,text='C').pack(side=RIGHT,expand=YES,fill=NONE) Button(root,text='D').pack(side=LEFT,expand=NO,fill=Y) Button(root,text='E').pack(side=TOP,expand=YES,fill=BOTH) Button(root,text='F').pack(side=BOTTOM,expand=YES) Button(root,text='G').pack(anchor=SE) root.mainloop()
Grid布局
from tkinter import * tk=Tk() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0) Label(tk,text="Second").grid(row=1)#第二行 #主事件循环 mainloop()
Place布局
'''1.使用绝对坐标将组件放到指定的位置''' # -*- coding: utf-8 -*- # 不设置root的大小,使用默认 from tkinter import * root = Tk() lb = Label(root, text='hello Place') # lb.place(relx = 1,rely = 0.5,anchor = CENTER) # 使用绝对坐标将Label放置到(0,0)位置上 lb.place(x=0, y=0, anchor=NW) root.mainloop() # x,y指定组件放置的绝对位置
参数详解
pack布局管理
pack布局非常简单,不用做过多的设置,直接使用一个 pack 函数就可以了。
1、我们使用 pack 函数的时候,默认先使用的放到上面,然 后依次向下排,它会给我们的组件一个自认为合适的位置和大小,这是默认方式。
2、可接受的参数:
side:停靠在哪个方向
left: 左
top: 上
right: 右
botton: 下
fill:填充
x:水平方向填充
y:竖直方向填充
both:水平和竖直方向填充
none:不填充
expand:
True:随主窗体的大小变化
False:不随主窗体的大小变化
anchor:
N:北 下
E:东 右
S:南 下
W:西 左
CENTER:中间
内外边距:
padx:x方向的外边距
pady:y方向的外边距
ipadx:x方向的内边距
ipady:y方向的内边距
Grid 布局管理
Pack 作为首选的布局管理方式,其运作方式并不是特别易于理解,已经由 Pack 布局完成的设计也很难做出改变。Grid 布局在1996年作为另一种可供选择的布局方式被引入,Grid 布局方式易学易用,但似乎大家还是习惯用 Pack。
Grid 在很多场景下是最好用的布局方式,相比而言,Pack 布局在控制细节方面有些力不从心。Place 布局虽然可以完全控制控件位置,但这也导致使用 Place 会比其他两种布局方式更加复杂。
Grid 把控件位置作为一个二维表结构来维护,即按照行列的方式排列控件:控件位置由其所在的行号和列号决定。行号相同而列号不同的几个控件会被彼此上下排列,列号相同而行号不同的几个控件会被彼此左右排列。
使用 Grid 布局的过程就是为各个控件指定行号和列号的过程,不需要为每个格子指定大小,Grid 布局会自动设置一个合适的大小。
Place 布局管理
Place 布局管理可以显式的指定控件的绝对位置或相对于其他控件的位置。要使用 Place 布局,调用相应控件的 place() 方法就可以了。所有 tkinter 的标准控件都可以调用 place()。
'''Tkinter教程之Place篇''' '''1.使用绝对坐标将组件放到指定的位置''' # -*- coding: cp936 -*- # 不设置root的大小,使用默认 from Tkinter import * root = Tk() lb = Label(root,text = 'hello Place') # lb.place(relx = 1,rely = 0.5,anchor = CENTER) # 使用绝对坐标将Label放置到(0,0)位置上 lb.place(x = 0,y = 0,anchor = NW) root.mainloop() # x,y指定组件放置的绝对位置 '''2.使用相对坐标放置组件位置''' # -*- coding: cp936 -*- # 不设置root的大小,使用默认 from Tkinter import * root = Tk() lb = Label(root,text = 'hello Place') # lb.place(relx = 1,rely = 0.5,anchor = CENTER) # 使用相对坐标(0.5,0.5)将Label放置到(0.5*sx,0.5.sy)位置上 lb.place(relx = 0.5,rely = 0.5,anchor = CENTER) root.mainloop() # relx,rely指定组件放置的绝对位置,范围为(0-1.0) '''3.使用place同时指定多个组件''' # -*- coding: cp936 -*- # 不设置root的大小,使用默认 from Tkinter import * root = Tk() root.geometry('800x600') lb = Label(root,text = 'hello Place') # lb.place(relx = 1,rely = 0.5,anchor = CENTER) # 使用相对坐标(0.5,0.5)将Label放置到(0.5*sx,0.5.sy)位置上 v = IntVar() for i in range(5): Radiobutton( root, text = 'Radio' + str(i), variable = v, value = i ).place(x = 80* i,anchor = NW) root.mainloop() # 使用place来指定各个Radiobutton的位置 '''4.同时使用相对和绝对坐标''' # 同时设置relx,rely和x,y的值 # -*- coding: cp936 -*- # 不设置root的大小,使用默认 from Tkinter import * root = Tk() root.geometry('800x600') lb1 = Label(root,text = 'hello Place',fg = 'green') lb2 = Label(root,text = 'hello Place',fg = 'red') # 先设置相对坐标为(0.5,0.5),再使用(-200,-200)将坐标作偏移(-200,-200) lb1.place(relx = 0.5,rely = 0.5,anchor = CENTER,x = -200,y = -200) # 先设置相对坐标为(0.5,0.5),再使用(-300,-300)将坐标作偏移(-300,-300) lb2.place(relx = 0.5,rely = 0.5,anchor = CENTER,x = -300,y = -300) root.mainloop() # 同时使用相对和绝对坐标时,相对坐标优先操作,然后是在这个相对坐标的基础上进行偏移 '''5.使用in来指定放置的容器''' # -*- coding: cp936 -*- # 使用in属性来指定放置到的容器是那一个 from Tkinter import * root = Tk() root.geometry('800x600') lb1 = Label(root,text = 'hello Place',fg = 'green') bt1 = Button(root,text = 'hello Place',fg = 'red') # 创建一个Label lb1.place(relx = 0.5,rely = 0.5,anchor = CENTER) # 在root同创建一个Button,目的是与bt1相比较 bt2 = Button(root,text = 'button in root',fg = 'yellow') bt2.place(anchor = W) # 在Label中创建一个Button bt1.place(in_ = lb1,anchor = W) root.mainloop() # 注意bt2放置的位置是在root的(0,0)处,而button1放置的位置是在lb1的(0,0)处,原因是由于bt1使用了in来指定放置的窗口为lb1 '''6.深入in用法''' # -*- coding: cp936 -*- # 使用in属性来指定放置到的容器是那一个,仅能是其master from Tkinter import * root = Tk() # root.geometry('800x600') # 创建两个Frame用作容器 fm1 = Frame(root,bg = 'red',width = 40,height = 40) fm2 = Frame(root,bg = 'blue',width = 40,height = 40) # 再在fm1中创建一个fm3 fm3 = Frame(fm1,bg = 'yellow',width = 20,height = 20) # 创建一个Label,它的master为fm1 lb1 = Label(fm1,text = 'hello Place',fg = 'green') lb1.place(in_ = fm1,relx = 0.5,rely = 0.5,anchor = CENTER) # 创建一个Button,它的master为fm1 bt1 = Button(fm1,text = 'hello Place',fg = 'red') # 将bt1放置到fm2中,程序报错 # 去掉下面这条语句就可以使用了,可以看到lb1已经正确的放置到fm1的中心位置了 # bt1.place(in_ = fm2,anchor = W) # 将上面的语句改为下面,即将bt1放置到其fm1的子组件fm3中,这样也是可以的 bt1.place(in_ = fm3,anchor = W) fm1.pack() fm2.pack() fm3.pack() root.mainloop() # in不是可以随意指定放置的组件的,如果使用in这个参数这个组件必需满足:是其父容器或父容器的子组件 '''7.事件与Place结合使用''' # -*- coding: cp936 -*- # 最后使用两个place方法来动态改变两个Frame的大小。 from Tkinter import * root = Tk() split = 0.5 fm1 = Frame(root,bg = 'red') fm2 = Frame(root,bg = 'blue') # 单击fm1时增大它的占有区域0.1 def incFm1(event): global split if split < 1: split += 0.1 fm1.place(rely = 0,relheight = split,relwidth = 1) fm2.place(rely = split,relheight = 1 - split,relwidth = 1) # 单击fm2时增大它的占有区域0.1 def incFm2(event): global split if split > 0: split -= 0.1 fm1.place(rely = 0,relheight = split,relwidth = 1) fm2.place(rely = split,relheight = 1 - split,relwidth = 1) # 这两语句要使用,不然开始看不到两个frame,也就没法点击它们了 fm1.place(rely = 0,relheight = split,relwidth = 1) fm2.place(rely = split,relheight = 1 - split,relwidth = 1) # 绑定单击事件 fm1.bind('<Button-1>',incFm1) fm2.bind('<Button-1>',incFm2) root.mainloop() # 为SplitWindow的原型了,再改动一下就可以实现一个SplitWindow了。
更多示例
Place布局 和 各种控件 简单演示
# -*-coding:utf-8-*- from tkinter import * class A: def __init__(self, master=None): self.root = master self.root.geometry('800x600+200+200') self.root.title('测试') # self.root.bind("<Motion>", self.call_back) self.frm1 = Frame(self.root) self.frm2 = Frame(self.root) self.frm3 = Frame(self.root) self.createpage() def call_back(self, event): print('现在的位置是:', event.x_root, event.y_root) def createpage(self): menu = Menu(self.root) self.root.config(menu=menu) filemenu = Menu(menu) menu.add_cascade(label='测试1', menu=filemenu) filemenu.add_command(label='1') filemenu.add_command(label='2') filemenu.add_command(label='3') onemenu = Menu(menu) menu.add_cascade(label='测试2', menu=onemenu) onemenu.add_command(label='1') onemenu.add_command(label='2') onemenu.add_command(label='3') self.frm1.config(bg='blue', height=500, width=600) Label(self.frm1, text='frm1').place(in_=self.frm1, anchor=NW) self.frm1.place(x=180, y=50) self.frm2.config(bg='red', height=500, width=150) Label(self.frm2, text='frm2').place(anchor=NW) self.frm2.place(x=20, y=50) self.frm3.config(bg='yellow', height=40, width=760) Label(self.frm3, text='frm3').place(in_=self.frm3, anchor=NW) self.frm3.place(x=20, y=5) # frm3下的Label Label(self.frm3, text='Label Test Test', fg='red', font='Verdana 10 bold').place(x=300, y=10) # frm2下的Button for i in range(9): Button(self.frm2, text='Button%d' % i).place(x=20, y=20+i*50, width=100) # frm1下的控件 Label(self.frm1, text='项目资源管理平台', fg='red', font='Verdana 10 bold').place(x=100, y=50, height=80, width=400) Button(self.frm1, text='1', height=1, width=1).place(x=450, y=450) Button(self.frm1, text='2', height=1, width=1).place(x=490, y=450) Button(self.frm1, text='3', height=1, width=1).place(x=530, y=450) if __name__ == '__main__': root = Tk() A(root) mainloop()
Python的图形界面开发库
Python 提供了多个图形开发界面的库,几个常用 Python GUI 库如下:
- Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。
- wxPython:wxPython 是一款开源软件,是 Python 语言的一套优秀的 GUI 图形库,允许 Python 程序员很方便的创建完整的、功能健全的 GUI 用户界面。
- Jython:Jython 程序可以和 Java 无缝集成。除了一些标准模块,Jython 使用 Java 的模块。Jython 几乎拥有标准的Python 中不依赖于 C 语言的全部模块。比如,Jython 的用户界面将使用 Swing,AWT或者 SWT。Jython 可以被动态或静态地编译成 Java 字节码。
动态计算各 Label 的大小和位置,并通过 place() 方法设置各 Label 的大小和位置
# Python 2.x使用这行 #from Tkinter import * # Python 3.x使用这行 from tkinter import * import random class App: def __init__(self, master): self.master = master self.initWidgets() def initWidgets(self): # 定义字符串元组 books = ('疯狂Python讲义', '疯狂Swift讲义', '疯狂Kotlin讲义',\ '疯狂Java讲义', '疯狂Ruby讲义') for i in range(len(books)): # 生成3个随机数 ct = [random.randrange(256) for x in range(3)] grayness = int(round(0.299*ct[0] + 0.587*ct[1] + 0.114*ct[2])) # 将元组中3个随机数格式化成16进制数,转成颜色格式 bg_color = "#%02x%02x%02x" % tuple(ct) # 创建Label,设置背景色和前景色 lb = Label(root, text=books[i], fg = 'White' if grayness < 120 else 'Black', bg = bg_color) # 使用place()设置该Label的大小和位置 lb.place(x = 20, y = 36 + i*36, width=180, height=30) root = Tk() root.title("Place布局www.tianqiweiqi.com") # 设置窗口的大小和位置 # width x height + x_offset + y_offset root.geometry("250x250+30+30") App(root) root.mainloop()
Place布局其他示例
'''2.使用相对坐标放置组件位置''' # -*- coding: utf-8 -*- # 不设置root的大小,使用默认 from tkinter import * root = Tk() lb = Label(root, text='hello Place') # lb.place(relx = 1,rely = 0.5,anchor = CENTER) # 使用相对坐标(0.5,0.5)将Label放置到(0.5*sx,0.5.sy)位置上 lb.place(relx=0.5, rely=0.5, anchor=CENTER) root.mainloop() # relx,rely指定组件放置的绝对位置,范围为(0-1.0) '''3.使用place同时指定多个组件''' # -*- coding: utf-8 -*- # 不设置root的大小,使用默认 from tkinter import * root = Tk() root.geometry('800x600') lb = Label(root, text='hello Place') # lb.place(relx = 1,rely = 0.5,anchor = CENTER) # 使用相对坐标(0.5,0.5)将Label放置到(0.5*sx,0.5.sy)位置上 v = IntVar() for i in range(5): Radiobutton( root, text='Radio' + str(i), variable=v, value=i ).place(x=80 * i, anchor=NW) root.mainloop() # 使用place来指定各个Radiobutton的位置 '''4.同时使用相对和绝对坐标''' # 同时设置relx,rely和x,y的值 # -*- coding: utf-8 -*- # 不设置root的大小,使用默认 from tkinter import * root = Tk() root.geometry('800x600') lb1 = Label(root, text='hello Place', fg='green') lb2 = Label(root, text='hello Place', fg='red') # 先设置相对坐标为(0.5,0.5),再使用(-200,-200)将坐标作偏移(-200,-200) lb1.place(relx=0.5, rely=0.5, anchor=CENTER, x=-200, y=-200) # 先设置相对坐标为(0.5,0.5),再使用(-300,-300)将坐标作偏移(-300,-300) lb2.place(relx=0.5, rely=0.5, anchor=CENTER, x=-300, y=-300) root.mainloop() # 同时使用相对和绝对坐标时,相对坐标优先操作,然后是在这个相对坐标的基础上进行偏移 '''5.使用in来指定放置的容器''' # -*- coding: utf-8 -*- # 使用in属性来指定放置到的容器是那一个 from tkinter import * root = Tk() root.geometry('800x600') lb1 = Label(root, text='hello Place Label', fg='green') bt1 = Button(root, text='hello Place Button', fg='red') # 创建一个Label lb1.place(relx=0.5, rely=0.5, anchor=CENTER) # 在root同创建一个Button,目的是与bt1相比较 bt2 = Button(root, text='button in root', fg='yellow') bt2.place(anchor=W) # 在Label中创建一个Button bt1.place(in_=lb1, anchor=W) root.mainloop() # 注意bt2放置的位置是在root的(0,0)处,而button1放置的位置是在lb1的(0,0)处,原因是由于bt1使用了in来指定放置的窗口为lb1 '''6.深入in用法''' # -*- coding: utf-8 -*- # 使用in属性来指定放置到的容器是那一个,仅能是其master from tkinter import * root = Tk() # root.geometry('800x600') # 创建两个Frame用作容器 fm1 = Frame(root, bg='red', width=40, height=40) fm2 = Frame(root, bg='blue', width=40, height=40) # 再在fm1中创建一个fm3 fm3 = Frame(fm1, bg='yellow', width=20, height=20) # 创建一个Label,它的master为fm1 lb1 = Label(fm1, text='hello Place', fg='green') lb1.place(in_=fm1, relx=0.5, rely=0.5, anchor=CENTER) # 创建一个Button,它的master为fm1 bt1 = Button(fm1, text='hello Place', fg='red') # 将bt1放置到fm2中,程序报错 # 去掉下面这条语句就可以使用了,可以看到lb1已经正确的放置到fm1的中心位置了 # bt1.place(in_ = fm2,anchor = W) # 将上面的语句改为下面,即将bt1放置到其fm1的子组件fm3中,这样也是可以的 bt1.place(in_=fm3, anchor=W) fm1.pack() fm2.pack() fm3.pack() root.mainloop() # in不是可以随意指定放置的组件的,如果使用in这个参数这个组件必需满足:是其父容器或父容器的子组件 '''7.事件与Place结合使用''' # -*- coding: utf-8 -*- # 最后使用两个place方法来动态改变两个Frame的大小。 from tkinter import * root = Tk() split = 0.5 fm1 = Frame(root,bg = 'red') fm2 = Frame(root,bg = 'blue') # 单击fm1时增大它的占有区域0.1 def incFm1(event): global split if split < 1: split += 0.1 fm1.place(rely = 0,relheight = split,relwidth = 1) fm2.place(rely = split,relheight = 1 - split,relwidth = 1) # 单击fm2时增大它的占有区域0.1 def incFm2(event): global split if split > 0: split -= 0.1 fm1.place(rely = 0,relheight = split,relwidth = 1) fm2.place(rely = split,relheight = 1 - split,relwidth = 1) # 这两语句要使用,不然开始看不到两个frame,也就没法点击它们了 fm1.place(rely = 0,relheight = split,relwidth = 1) fm2.place(rely = split,relheight = 1 - split,relwidth = 1) # 绑定单击事件 fm1.bind('<Button-1>',incFm1) fm2.bind('<Button-1>',incFm2) root.mainloop() # 为SplitWindow的原型了,再改动一下就可以实现一个SplitWindow了。
Grid布局其他示例:
注意:不要试图在一个主窗口中混合使用pack和grid
(1)标签控件
from tkinter import * tk=Tk() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0) Label(tk,text="Second").grid(row=1)#第二行 #主事件循环 mainloop()
(2) 输入控件
from tkinter import * tk=Tk() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0) Label(tk,text="Second").grid(row=1)#第二行 #输入控件 Entry(tk).grid(row=0,column=1) Entry(tk).grid(row=1,column=1) #主事件循环 mainloop()
(3)sticky参数的使用
from tkinter import * tk=Tk() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0,sticky=E)#靠右 Label(tk,text="Second").grid(row=2,sticky=W)#第二行,靠左 #输入控件 Entry(tk).grid(row=0,column=1) Entry(tk).grid(row=2,column=1) #主事件循环 mainloop()
(4)columnspan和rowspan参数的使用
columnspan选项可以指定控件跨越多列显示,而rowspan选项同样可以指定控件跨越多行显示。
from tkinter import * tk=Tk() var=IntVar() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0,sticky=E)#靠右 Label(tk,text="Second").grid(row=1,sticky=W)#第二行,靠左 #输入控件 Entry(tk).grid(row=0,column=1) Entry(tk).grid(row=1,column=1) button=Checkbutton(tk,text="Precerve aspect",variable=var) button.grid(sticky=W) #主事件循环 mainloop()
跨越两列显示如下
from tkinter import * tk=Tk() var=IntVar() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0,sticky=E)#靠右 Label(tk,text="Second").grid(row=1,sticky=W)#第二行,靠左 #输入控件 Entry(tk).grid(row=0,column=1) Entry(tk).grid(row=1,column=1) button=Checkbutton(tk,text="Precerve aspect",variable=var) button.grid(columnspan=2,sticky=W) #主事件循环 mainloop()
from tkinter import * tk=Tk() var=IntVar() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0,sticky=E)#靠右 Label(tk,text="Second").grid(row=1,sticky=W)#第二行,靠左 #输入控件 Entry(tk).grid(row=0,column=1) Entry(tk).grid(row=1,column=1) #多选框插件 button=Checkbutton(tk,text="Precerve aspect",variable=var) button.grid(row=2,columnspan=2,sticky=W) #插入图片 photo=PhotoImage(file="python_logo.gif") label=Label(image=photo) label.image=photo label.grid(row=0,column=2) #主事件循环 mainloop()
from tkinter import * tk=Tk() var=IntVar() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0,sticky=E)#靠右 Label(tk,text="Second").grid(row=1,sticky=W)#第二行,靠左 #输入控件 Entry(tk).grid(row=0,column=1,padx=10,pady=10) Entry(tk).grid(row=1,column=1) #多选框插件 button=Checkbutton(tk,text="Precerve aspect",variable=var) button.grid(row=2,columnspan=2,sticky=W) #插入图片 photo=PhotoImage(file="python_logo.gif") label=Label(image=photo) label.image=photo label.grid(row=0,column=2,rowspan=2,columnspan=2, sticky=W+E+N+S, padx=5, pady=5)#合并两行,两列,居中,四周外延5个长度 #主事件循环 mainloop()
(5)
from tkinter import * tk=Tk() var=IntVar() #标签控件,显示文本和位图,展示在第一行 Label(tk,text="First").grid(row=0,sticky=E)#靠右 Label(tk,text="Second").grid(row=1,sticky=W)#第二行,靠左 #输入控件 Entry(tk).grid(row=0,column=1,padx=10,pady=10) Entry(tk).grid(row=1,column=1) #多选框插件 button=Checkbutton(tk,text="Precerve aspect",variable=var) button.grid(row=2,columnspan=2,sticky=W) #插入图片 photo=PhotoImage(file="python_logo.gif") label=Label(image=photo) label.grid(row=0,column=2,rowspan=2,columnspan=2, sticky=W+E+N+S, padx=5, pady=5)#合并两行,两列,居中,四周外延5个长度 #按钮控件 button1=Button(tk,text="Zoom in") button1.grid(row=2,column=2) button2=Button(tk,text="Zoom out") button2.grid(row=2,column=3) #主事件循环 mainloop()
(6)padx和pady参数的应用
from tkinter import * import time t = Tk() t.title('与python聊天中') #创建frame容器 frmLT = Frame(width=500, height=320, bg='white') frmLC = Frame(width=500, height=150, bg='red') frmLB = Frame(width=500, height=30) frmRT = Frame(width=200, height=500) frmLT.grid(row=0, column=0) frmLC.grid(row=1, column=0) frmLB.grid(row=2, column=0) frmRT.grid(row=0, column=1, rowspan=3)
from tkinter import * import time t = Tk() t.title('与python聊天中') #创建frame容器 frmLT = Frame(width=500, height=320, bg='white') frmLC = Frame(width=500, height=150, bg='red') frmLB = Frame(width=500, height=30) frmRT = Frame(width=200, height=500) frmLT.grid(row=0, column=0,padx=1,pady=3) frmLC.grid(row=1, column=0,padx=1,pady=3) frmLB.grid(row=2, column=0) frmRT.grid(row=0, column=1, rowspan=3,padx=2,pady=3)
利用padx和pady,可以将框架边界区分开
from tkinter import * import time t = Tk() t.title('与python聊天中') #创建frame容器 frmLT = Frame(width=500, height=320, bg='white') frmLC = Frame(width=500, height=150, bg='red') frmLB = Frame(width=500, height=30) frmRT = Frame(width=200, height=500) frmLT.grid(row=0, column=0,padx=1,pady=3) frmLC.grid(row=1, column=0,padx=1,pady=3) frmLB.grid(row=2, column=0) frmRT.grid(row=0, column=1, rowspan=3,padx=2,pady=3) '''#固定容器大小 frmLT.grid_propagate(0) frmLC.grid_propagate(0) frmLB.grid_propagate(0) frmRT.grid_propagate(0)''' #添加按钮 btnSend = Button(frmLB, text='发 送', width = 8)#在frmLB容器中添加 btnSend.grid(row=2,column=0) btnCancel = Button(frmLB, text='取消', width = 8) btnCancel.grid(row=2,column=1,sticky=E) #添加图片 imgInfo = PhotoImage(file = "python_logo.gif") lblImage = Label(frmRT, image = imgInfo) lblImage.image = imgInfo lblImage.grid() #固定容器大小 frmLT.grid_propagate(0) frmLC.grid_propagate(0) frmLB.grid_propagate(0) frmRT.grid_propagate(0)