Python tkinter 复杂界面小部件布局

大家在编写python tkinter 界面时,经常被小部件的布局困扰,我再写了几个小工具后,对布局有了一些心得,现分享给大家,也希望大家能编写出更漂亮的界面。

第一步,选择布局方式
tkinter 提供了三种布局方式:
1、pack() 排列方式,如果小部件按横向或竖向对齐排列的,可选用这种方式,类似网页中的层概念,强烈建议先用;
2、grid() 网格方式,如果小部按网格规律排列的,则可选这种方式,类似网页中的表格概念;
3、place() 精准方式,会按坐标值进行布局,虽然能很精准地布局,但需要不停地调整位置花费大量时间,且在不同的运行环境可能导致小部件在容器中显示不全,不建议使用。

前两种方式在同一容器内(父小部件)不可混用,后者则可以强加到前两者的容器中。

前两方式控制小部件之间的间隔距离,在布局方法中加入属性 padx、pady 来实现,单位是像素值,一般设2左右就可以了。小部件的宽、高度则在小部件主体中用 width、height 来控制,注意这里的单位是按字符来定义(1个字符约为7个像素点),而 place 则是按像素来计算,即如小部件中定义了 width=20,后面用 pack 或 grid 来布局时,则表示小部件的宽度为20个字符,若用 place 来定位布局,则表示小部件的宽度为 20 个像素宽。还有一点要注意,button、label 小部件在使用image 显示图片后,宽高度会强制转为像素单位。

前两种方式在布局时需根据小部件的排列进行合理分组,使用 pack 布局时调用它的顺序还会导致不同的效果;grid 调用的顺序倒不讲究,全由 row 、 column 来决定位置;place 则更是随意。

总之,如果小部件布置成横向排列(不成网格状,也是最常见的),这时请用 pack 布局;如果成网格状排列(中间可以存在跨行、跨列情况)则使用 grid 布局;若小部件位置分散就建议用 place 了。

第二步,划分区域
这步很关键,也是最难控制的一环,若想象能力不强的建议画草图辅助,分区的方式每次只能按横向或纵向进行,复杂的界面需要多次嵌套分区。我先用我写过的小工具界面做为例子进行分区。
布局分区实例
根据上图小部件的分布情况,先划分第一层分区,现按红色框按上下结构分区(图中蓝色框为第二层分区,橙色框为第三层,棕色框为第四层),关键代码(为了方便理解,把不同层做成缩进格式,实现代码不能缩进):

f1=tkinter.Frame(root)
f1.pack(side=tkinter.TOP,pady=2,fill=tkinter.X) #横向占满空间
    tkinter.Button(f1,width=3).pack(side=tkinter.LEFT,padx=2)#以 f1 做为容器
    tkinter.Button(f1,width=3).pack(side=tkinter.LEFT,padx=2)#以 f1 做为容器

f2=tkinter.Frame(root)
f2.pack(side=tkinter.TOP,pady=2,fill=tkinter.X)

    f4=tkinter.Frame(f2) #以 f2 做为容器
    f4.pack(side=tkinter.TOP,fill=tkinter.X)

        f8=tkinter.Frame(f4) #以 f4 做为容器
        f8.pack(side=tkinter.LEFT,fill=tkinter.Y) #纵向占满空间
        tkinter.Label(text="……\n……").pack(padx=2)#控制前后间隔,不设宽度会根据文本长度自行调整

        f9=tkinter.Frame(f4)
        f9.pack(side=tkinter.LEFT,fill=tkinter.Y)

            f12=tkinter.Frame(f9) #以 f9 做为容器
            f12.pack(side=tkinter.TOP,pady=2,fill=tkinter.X)
                tkinter.Radiobutton(f12,text="……").pack(side=tkinter.LEFT,padx=2)#以 f12 做为容器
                ttk.Combobox(f12,width=20).pack(side=tkinter.LEFT,padx=2) #用 width 控制长度
                ttk.Combobox(f12).pack(side=tkinter.LEFT,padx=2,fill=tkinter.X) #可先其中一小部件充满剩余空间,使界面好看些

        f13=tkinter.Frame(f9) #以 f9 做为容器
        f13.pack(side=tkinter.TOP,pady=2,fill=tkinter.X)
        	#……
            tkinter.Entry(f13).pack(side=tkinter.LEFT,fill=tkinter.X)#以 f13 做为容器

    f5=tkinter.Frame(f2) #以 f2 做为容器
    f5.pack(side=tkinter.TOP,fill=tkinter.X)
    	#……

f3=tkinter.Frame(root)
f3.pack(side=tkinter.TOP,pady=2,fill=tkinter.BOTH,expand=True) #充满窗体剩余空间

    f6=tkinter.LabelFrame(f3,text="书目结构") #以 f3 做为容器
    f6.pack(side=tkinter.LEFT,fill=tkinter.Y)#纵向占满空间

        f10=tkinter.Frame(f6) #以 f6 做为容器
        f10.pack(side=tkinter.TOP,fill=tkinter.X)

        f11=tkinter.Frame(f6) #以 f6 做为容器
        f11.pack(side=tkinter.TOP,fill=tkinter.BOTH,expand=True)#占满剩余空间

    f7=tkinter.LabelFrame(f3,text="内容预览") #以 f3 做为容器
    f7.pack(side=tkinter.LEFT,fill=tkinter.BOTH,expand=True)#纵向占满空间
    
        tkinter.Scrollbar(f7,orient=tkinter.VERTICAL).pack(side=tkinter.RIGHT,fill=tkinter.Y)#先布局,避免有时被挤掉
        tkinter.Text(f7).pack(side=tkinter.LEFT,fill=tkinter.BOTH,expand=True)#占满剩余空间

    
tkinter.Text(height=2).pack(side=tkinter.TOP,fill=tkinter.X,pady=2) #仅1个小部件,所以省掉 Frame 直接使用小部件

每个顶层的小部件基本都会按横向对齐排列,因此均用 pack(side=tkinter.LEFT,padx=2) 排列即可 ,为了界面更加好看,每一行中选其中一个小部件自动拉长充满剩余空间(关键代码: fill=tkinter.X,有时需要再加上 expand=True )

分好区(层)后,若某一区小部件为网格分布,则该层的小部件可换用 grid()来布局,如下图(橙色线为网格划分):
布局混用实例
直接上关键代码:

f1=tkinter.Frame(root)
f1.pack(side=tkinter.LEFT)

    tkinter.Label(f1,text=" 书籍名称 ").grid(row=0,column=0,pady=2) #文本前后加空间来实现间隔
    tkinter.Entry(f1,width=20).grid(row=0,column=1,padx=2,pady=2) # row=行控制, column 列控制
    tkinter.Label(f1,text=" 作者 ").grid(row=0,column=2,pady=2)
    tkinter.Entry(f1,width=20).grid(row=0,column=3,padx=2,pady=2) # row=行控制, column 列控制

    tkinter.Label(f1,text=" 出 版 社 ").grid(row=1,column=0,pady=2)
    tkinter.Entry(f1,width=20).grid(row=1,column=1,padx=2,pady=2)
    tkinter.Label(f1,text=" 日期 ").grid(row=1,column=2,pady=2)
    tkinter.Entry(f1,width=20).grid(row=1,column=3,padx=2,pady=2)

    tkinter.Label(f1,text=" 封面图片 ").grid(row=2,column=0,pady=2)
    tkinter.Entry(f1,width=20).grid(row=2,column=1,padx=2,pady=2)
    f3=tkinter.Frame(f1).grid(row=2,column=2,columnspan=2,pady=2) #横跨2列

        tkinter.Button(f3,text="浏览").pack(side=tkinter.LEFT,padx=2) #该层中所有小部件均用 pack 布局
        #……

f2=tkinter.Frame(root,width=30) #容器也可以定义尺寸,不定义则以最大包含量来算
f2.pack(side=tkinter.LEFT)

    tkinter.Label(f2).pack(fill=tkinter.BOTH,expand=True)

第三步,层内小部件的排列顺序
一般小部件都会放在最上层排列,可用 pack 按上下左右四个方向来布局(同一层中最好只按横向或纵向,比如 前面用 side=tkinter.LEFT 放置后,后面小部件又用 tkinter.TOP 来放置,虽然不会报错,但效果不可控。但可以再用 tkinter.RIGHT 来放置)。

pack 方法有先来后到之分,调用时要注意顺序,在添加自动填充空间的小部件时,后面添加的小部件可能会被挤掉,这时可以把后面部件调到前面先放置,再放置自动填充空间的小部件,如:

f1=tkinter.Frame(root)
f1.pack(side=tkinter.TOP,fill=tkinter.BOTH,expand=True)

tkinter.Text(f1).pack(side=tkinter.LEFT,fill=tkinter.BOTH,expand=True)
tkinter.Scrollbar(f1,orient=tkinter.VERTICAL).pack(side=tkinter.LEFT,fill=tkinter.Y)

带垂直滚动条的文本框,按上面顺序放置,可能滚动条会被挤掉不显示,因此可以把放置顺序改下就可以避免这种情况:

f1=tkinter.Frame(root)
f1.pack(side=tkinter.TOP,fill=tkinter.BOTH,expand=True)

tkinter.Scrollbar(f1,orient=tkinter.VERTICAL).pack(side=tkinter.RIGHT,fill=tkinter.Y)#先放置滚动条,右对齐
tkinter.Text(f1).pack(side=tkinter.LEFT,fill=tkinter.BOTH,expand=True)#后放置的文本框左对齐

小技巧

看到这里,相信大家应该能做出复杂的界面了,但中间的调试是免不了的,调试又是最耗时的,因此大家在划区分层时,最好先把 Frame 换成 LabelFrame,这个容器会显示边框,能让大家更直观地看到分区效果。或者给 Frame 加上不同的背景色,也能减少很多调试时间!

最后,愿大家能做出更美的程序界面!!

  • 16
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Python Tkinter中的place布局是一种基于绝对位置的布局方式,它允许您将小部件放置在窗口的任何位置。使用place布局,您可以指定小部件的x和y坐标,以及它们的宽度和高度。这种布局方式非常适合创建自定义的用户界面,但需要更多的手动调整和计算。 ### 回答2: TkinterPython中最常用的GUI工具包之一,它可以创建各种图形用户界面,包括按钮、菜单、文本框、标签等等。其中,Tkinter中有三种布局方式,即pack、grid和place布局。 place布局是最简单、最灵活的布局方式。它允许你自由地放置组件在窗口中的任何位置。通过place布局,可以通过指定组件的坐标和尺寸,自定义布局。详细来说,place布局采用以下语法: widget.place(options) 其中,widget为需要进行布局的组件,options为可选的选项。下面是常用的选项: - x和y:指定组件的坐标位置 - width和height:指定组件的宽度和高度 - anchor:指定组件在其位置内的位置 - bordermode:指定组件的边框模式 例如,下面是用place布局创建一个简单的窗口的例子: ``` Python import tkinter as tk root = tk.Tk() label = tk.Label(root, text="Hello, Tkinter!") label.place(x=50, y=50) root.mainloop() ``` 在上面的例子中,使用place布局创建了一个标签,这个标签的位置为(50, 50)。 需要注意的是,place布局容易导致组件之间的重叠和覆盖。因此,在使用place布局时,需要仔细地指定组件的位置和尺寸,以避免出现这种问题。 综上所述,place布局是一种非常灵活的布局方式,允许我们自由地布置组件。但是,需要注意组件之间的重叠和覆盖问题。在使用place布局时,需要精心指定组件的位置和尺寸,以实现理想的布局效果。 ### 回答3: Python tkinter是一个常用的GUI界面工具包,其中place布局是一种常用的定位布局方式。place布局适用于需要定位、对齐和调整控件位置的情况,可以通过具体的坐标值来指定控件位置。下面我将从以下几个方面详细介绍Python tkinter中的place布局。 1. 布局方法 place布局可以通过以下方法来指定控件位置: 1). x和y坐标值:通过指定控件的x和y坐标值来设置控件的位置,如widget.place(x=10, y=20)。 2). relx和rely坐标值:通过指定控件相对于父容器的相对坐标值来设置控件位置,如widget.place(relx=0.5, rely=0.5)。 3). anchor参数:用于指定控件的位置锚点,如widget.place(x=10, y=20, anchor="nw"),表示从控件的左上角开始布局。 2. 布局属性 place布局还可以通过以下属性来设置控件的布局和大小: 1). width和height属性:用于设置控件的宽度和高度,如widget.place(x=10, y=20, width=100, height=50)。 2). relwidth和relheight属性:用于设置控件相对于父容器的宽度和高度比例,如widget.place(relx=0.5, rely=0.5, relwidth=0.5, relheight=0.5)。 3). bordermode属性:用于指定控件的边框模式,有inside和outside两种,如widget.place(x=10, y=20, width=100, height=50, bordermode="outside")。 3. 注意事项 在使用place布局时,需要注意以下几个问题: 1). 控件的位置和大小需要根据父容器的大小进行调整,避免超出或空缺的问题。 2). 在布局时,需要注意控件之间的间距和重叠情况,避免影响视觉效果。 3). 当控件的位置和大小需要根据窗口大小自适应时,需要使用bind方法来绑定事件,通过event.width和event.height属性来动态调整控件位置和大小。 以上就是Python tkinter中的place布局的基本情况介绍,希望对大家的学习和使用有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jumpbull01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值