Python | GUI | Tkinter - 1. 基本控件

16 篇文章 3 订阅
12 篇文章 0 订阅

本文对总结 Tkinter 环境的准备以及基本控件的使用 1234

使用软件环境: conda 22.9.0tk 8.6.11

Updated: 2022 / 12 / 20


系列文章

  • Python | GUI | Tkinter - 1. 基本控件 5
  • Python | GUI | Tkinter - 2. 组件使用 6
  • Python | GUI | Tkinter - 3. 多窗体 7
  • Python | GUI | Tkinter - 4. 多线程的暂停和继续以及文件间调用 8

Python | GUI | Tkinter - 1. 基本控件


总览

Python 使用了不同的 GUI 应用程序,这些应用程序在与用户使用的应用程序进行交互时对用户很有帮助。Python 基本上使用 3 个,GUITkinterwxPythonPyQt。所有这些都可以在 WindowsLinuxmac-OS 上运行。但是这些 GUI 应用程序具有许多小部件,即有助于用户与应用程序交互的控件。其中的一些小部件是按钮、列表框、滚动条和树状视图等 9


前言

概念

Tkinter(音为 tea-kay-inter)是 TkPython 接口,TkTcl / TkGUI 工具包。

  • Tcl(工具命令语言, 音为 tickle )是嵌入式应用程序,测试,原型设计和 GUI 开发领域的流行脚本语言。
  • 另一方面,Tk 是一个开源的多平台小部件工具包,许多不同语言都使用它来构建 GUI 程序。而 Tkinter 只是一个使用 Tcl / Tk 库的 C 扩展的包装器。

什么是 Tcl ? 参考这里 10111213

Tkinter 的优势, 简单易学(比 Python 的其他 GUI 库简单),跨平台,标准库,无需安装。

GUI 编程的三个核心问题:

  1. 屏幕上应显示哪些组件? 认识组件的形态;
  2. 组件应该放在哪里? 学习组件布局;
  3. 组件如何交互? 组件中的事件;

比较

tkinter 同其他的比较,比如 PyQtwxPython,参考这里 14


环境

安装 python3.8.11tk 8.6.11
安装编辑器,演示使用的是 Pycharm
使用的系统版本是 macOS Big Sur Version 11.4


Tkinter 创建窗口

窗口

  • 1. 创建窗口
import tkinter as tk  
root = tk.Tk()  		      	 		 
# Tk()的作用就是创建一个窗口

如果只是执行以上的两句代码,运行程序是没有反应的,因为只有一个主函数,从上到下执行完就没有了,这个窗口也是很快就消失了,所以现在我们要做的就是让窗口一直显示,那么我们就可以加一个循环

创建的窗口的名字是 root ,那么我们之后使用这个 root 就可以操作这个窗口了。

root.mainloop()  

执行以上的3句代码,我们就可以看见窗口了

在这里插入图片描述


  • 2. 窗口标题
root.title('窗口标题')

在这里插入图片描述

  • 3. 窗口尺寸
root.geometry("300x100+630+80") 

该方法需要传入一个固定格式的字符串,格式 wxh±x±y
其中 wh 表示窗口的宽和高
xy 表示窗口显示位置的横向和纵向坐标
+- 则表示正方向还是负方向,基于屏幕左上角为坐标原点,向下或向右为正方向

注意,当窗口大小不固定时,是通过动态获取根窗口的宽高来计算位置,如果窗口的宽高一开始就是确定的,请使用确定值,尽量避免动态获取窗口的大小,以免影响 GUI 的流畅。

使窗口居中的方法可参考 15
在这里插入图片描述

  • 4. 创建按钮

调用 Button() 即可创建这个组件,创建的这个组件我们赋值给一个常量,以后我们就可以用这个常量来操作这个按钮:

btn1 = tk.Button(root)
# 将我们创建的按钮放到这个窗口root上面

btn1["text"] = "点击"
# 给按钮取一个名称为 ‘点击’

btn1.pack()
# 我们创建的按钮组件,已经放到窗口里面了,但是放到窗口的哪个位置,我们就可以用
# pack()去定位(后面会介绍其它定位方法)

创建点击按钮事件的弹窗,先导入messagebox,这个必须单独导入

from tkinter import messagebox
def test(e):
    messagebox.showinfo("窗口名称","点击成功")

现在有了按钮,有了方法,我想要做的是一点击按钮,就执行这个方法,那么就需要将按钮和方法进行绑定,按钮组件里面有一个方法 bind() 这个方法就可以实现绑定

btn1.bind("<Button-1>",test) 
# 第一个参数为:按鼠标左键的事件 第二个参数为:要执行的方法的名字

# 或者
# btn1 = tk.Button(root, text='点击', command=test)

完整代码如下所示:

import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
root.title('窗口标题')
root.geometry("300x100+630+80")

btn1 = tk.Button(root)
btn1['text'] = '点击'
btn1.pack()

def test(e):
    messagebox.showinfo('窗口名称', '点击成功')

btn1.bind('<Button-1>', test)
root.mainloop()

在这里插入图片描述
在这里插入图片描述

布局

所谓布局,就是指控制窗体容器中各个控件(组件)的位置关系。
tkinter 共有3种几何布局管理器,分别是 pack 布局,grid 布局,place 布局。

布局管理器特点
pack要么将组件垂直的排列,要么水平的排列
gridgrid (网格)布局管理器会将控件放置到一个二维的表格里。主控件被分割成一系列的行和列,表格中的每个单元 (cell) 都可以放置一个控件。

grid_info() 可查看组件默认的参数。
例如,{'in': <tkinter.Tk object .>, 'column': 0, 'row': 0, 'columnspan': 1, 'rowspan': 1, 'ipadx': 0, 'ipady': 0, 'padx': 0, 'pady': 0, 'sticky': ''}
place

pack 管理器

概念

使用 pack 布局,将向容器中添加组件,第一个添加的组件在最上方,然后是依次向下添加。当 pack 布局不设置属性时,它只会占用能容纳下当前组件的最小空间。

pack 布局区分以下三种空间:

  • 所属不明的,无人认领的空间;
  • 要求但未使用的空间;
  • 要求并已使用的空间;

expandfill 属性有什么区别?——
expand 对应的正是要求但未使用的空间,而 fill 对应的是要求并已使用的空间。fill 是填满的意思,将所有要求的空间占满。


属性
选项含义
fill设置组件是否向水平或垂直方向填充。取值可以有 XYBOTHNONE

fill = X(水平方向填充)
fill = Y(垂直方向填充)
fill = BOTH(水平和垂直)
NONE 不填充
expand设置组件是否展开。取值可以有 YESNO(1、0)

当值为 YES 时,side 选项无效。组件显示在父容器中心位置;
fill 选项为 BOTH ,则填充父组件的剩余空间。默认为不展开。
side设置组件的对齐方式。取值可以为左(LEFT)、上(TOP)、右(RIGHT)、下(BOTTOM)。
ipadx、ipady设置 x 方向(或者 y 方向)内部间隙(子组件之间的间隔),可设置数值,默认是 0,非负整数,单位为像素。
padx、pady设置 x 方向(或者y方向)外部间隙(与之并列的组件之间的间隔)。可设置数值,默认是 0。非负整数,单位为像素。
anchor锚选项,当可用空间大于所需求的尺寸时,决定组件被放置于容器的何处。NESWNWNESWSECENTER(默认值为 CENTER),表示八个方向以及中心。

方法
方法作用
pack_slaves()以列表方式返回本组件的所有子组件对象。
pack_configure(option=value)pack 布局管理器设置属性,使用属性(option)= 取值(value)方式设置
propagate(boolean)设置为 True 表示父组件的几何大小由子组件决定(默认值),反之则无关。
pack_info()返回 pack 提供的选项所对应的值。
pack_forget()Unpack 组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用pack(option, …),将其显示。
location(x, y)x, y 为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1) 表示不在其中
size()返回组件所包含的单元格,揭示组件大小。

示例
import tkinter as tk

root = tk.Tk()
frame = tk.Frame(root)

tk.Label(frame, text="Pack 布局的 side 和 fill").pack()
tk.Button(frame, text="A").pack(side=tk.LEFT, fill=tk.Y)
tk.Button(frame, text="B").pack(side=tk.TOP, fill=tk.X)
tk.Button(frame, text="C").pack(side=tk.RIGHT, fill=tk.NONE)
tk.Button(frame, text="D").pack(side=tk.TOP, fill=tk.BOTH)

# 需注意,顶部框架不会展开,也不会填充X或Y方向
frame.pack()

tk.Label(root, text="Pack 布局的 expand").pack()
tk.Button(root, text="我不扩展").pack()
tk.Button(root, text="我不向x方向填充,但我扩展1").pack(expand=1)
tk.Button(root, text="我不向x方向填充,但我扩展5").pack(expand=5)
tk.Button(root, text="我向x方向填充,并且扩展").pack(fill=tk.X, expand=1)

在这里插入图片描述


from tkinter import *

root = Tk()
fm1 = Frame(root)

Button(fm1, text='Top').pack(side=TOP, anchor=W, fill=X, expand=YES)
Button(fm1, text='Center').pack(side=TOP, anchor=W, fill=X, expand=YES)
Button(fm1, text='Bottom').pack(side=TOP, anchor=W, fill=X, expand=YES)
fm1.pack(side=LEFT, fill=BOTH, expand=YES)

fm2 = Frame(root)
Button(fm2, text='Left').pack(side=LEFT)
Button(fm2, text='This is the Center button').pack(side=LEFT)
Button(fm2, text='Right').pack(side=LEFT)
fm2.pack(side=LEFT, padx=10)

root.mainloop()

在这里插入图片描述


grid 管理器

概念

又被称作网格布局,是最被推荐使用的布局。程序大多数都是矩形的界面,我们可以很容易把它划分为一个几行几列的网格,然后根据行号和列号,将组件放置于网格之中。

使用 grid 布局时,需要在里面指定两个参数,分别用 row 表示行,column 表示列。需要注意的是 rowcolumn 的序号都从 0 开始,且每个网格只能容纳一个窗口小控件。

要注意,每列的宽度(或每行的高度)由网格中小部件的高度或宽度决定。如果需要额外的设置,只能通过设置网格中的小部件的宽度实现。 另外,可以使用sticky = tk.NSEW 参数使小部件可扩展并填充网格的整个单元格。

在tkinter的官方文档中,并没有给出让 grid 布局适配根窗口拉伸的方法,但是通过查阅 tcl/Tk 的文档,可知设置权重能满足该需求。
比如,

# 第一个参数是想要设置的列/行的序号, 第二个参数是比例

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

属性
选项含义
column列号,设置将组件放置于第几列。取值为列的序号,不是列数。
columnspan跨列,跨越的列数,正整数。
row行号,设置将组件放置于第几行。取值为行的序号,不是行数。
rowspan跨行,跨越的行数,正整数。
ipadx, ipady设置子组件之间的间隔,x 方向或 y 方向,默认单位为像素,非浮点数,默认 0.0
padx, pady与之并列的组件之间的间隔,x 方向或 y 方向,默认单位为像素,非浮点数,默认 0.0
sticky组件紧贴所在的单元格的某一脚,对应于东南西北中以及4个角。东 = e,南 = s,西 = w,北 = nneseswnw,类似于 pack 布局中的锚选项。

sticky=tk.NE 右上角;
sticky=tk.SE 右下角;
sticky=tk.SW 左下角;
sticky=tk.NW 左上角;
sticky=tk.N+tk.S 垂直拉伸小控件,并保持水平居中,其等价于字符串值 ns,以下同;
sticky=tk.E+tk.W 水平拉伸且持垂直居中;
sticky=tk.N+tk.E+tk.S+tk.W 水平和垂直拉伸,等价于常量 tk.NSEW 和字符串值 nsew
sticky=tk.N+tk.S+tk.W 将垂直拉伸并向西(左)对齐
  • column 指定控件所在的列

在这里插入图片描述


  • padx 水平方向外边距:

在这里插入图片描述

  • pady 垂直方向外边距

在这里插入图片描述


  • sticky 组件东南西北的方向

在这里插入图片描述


  • row 指定控件所在的行

在这里插入图片描述

  • ipadx 水平方向内边距

在这里插入图片描述


  • ipady 垂直方向内边距

在这里插入图片描述

方法
方法作用
grid_slaves()以列表方式返回本组件的所有子组件对象。
grid_configure(option=value)grid 布局管理器设置属性,使用属性(option)= 取值(value)方式设置
grid_propagate(boolean)设置为 True 表示父组件的几何大小由子组件决定(默认值),反之则无关。
grid_info()返回 grid 提供的选项所对应的值。
grid_forget()Unpack 组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用grid(option, …),将其显示。
grid_location(x, y)x, y 为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1) 表示不在其中
size()返回组件所包含的单元格,揭示组件大小。

示例
1.
from tkinter import *

root = Tk()

Label(root, width=15, height=3, bg="red").grid(row=0, column=0)
Label(root, width=15, height=3, bg="green").grid(row=0, column=1)
Label(root, width=15, height=3, bg="blue").grid(row=0, column=2)
Label(root, width=15, height=3, bg="white").grid(row=1, column=0)
Label(root, width=15, height=3, bg="black").grid(row=1, column=1)
Label(root, width=15, height=3, bg="grey").grid(row=1, column=2)

root.mainloop()

在这里插入图片描述


如果再加上 root.grid_columnconfigure(x, weight=1), root.grid_rowconfigure(x, weight=1) 以确保控件大小根据跟窗口大小自适应放大或者缩小,如下所示:

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

在这里插入图片描述


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

在这里插入图片描述


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

在这里插入图片描述

2.
import tkinter as tk

root = tk.Tk()
root.title('Find & Replace')

tk.Label(root, text="Find:").grid(row=0, column=0, sticky='e')
tk.Entry(root, width=60).grid(row=0, column=1, padx=2, pady=2, sticky='we', columnspan=9)

tk.Label(root, text="Replace:").grid(row=1, column=0, sticky='e')
tk.Entry(root).grid(row=1, column=1, padx=2, pady=2, sticky='we', columnspan=9)

tk.Button(root, text="Find").grid(row=0, column=10, sticky='e' + 'w', padx=2, pady=2)
tk.Button(root, text="Find All").grid(row=1, column=10, sticky='e' + 'w', padx=2)
tk.Button(root, text="Replace").grid(row=2, column=10, sticky='e' + 'w', padx=2)
tk.Button(root, text="Replace All").grid(row=3, column=10, sticky='e' + 'w', padx=2)

tk.Checkbutton(root, text='Match whole word only ').grid(row=2, column=1, columnspan=4, sticky='w')
tk.Checkbutton(root, text='Match Case').grid(row=3, column=1, columnspan=4, sticky='w')
tk.Checkbutton(root, text='Wrap around').grid(row=4, column=1, columnspan=4, sticky='w')

tk.Label(root, text="Direction:").grid(row=2, column=6, sticky='w')
tk.Radiobutton(root, text='Up', value=1).grid(row=3, column=6, columnspan=6, sticky='w')
tk.Radiobutton(root, text='Down', value=2).grid(row=3, column=7, columnspan=2, sticky='e')

root.mainloop()

在这里插入图片描述

place 管理器

概念

place 布局管理器可以通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景。但是不太推荐使用,因为在不同分辨率下界面往往有较大差异。


属性
选项
x, y组件左上角的绝对坐标(相当于窗口),整数,默认值 0
relx ,rely组件左上角的坐标(相对于父容器),0~1之间浮点数。相对位置,0.0 表示左边缘(或上边缘),1.0 表示右边缘(或下边缘)。
width , height组件的宽度和高度,非负整数。
relwidth , relheight组件的宽度和高度(相对于父容器),0~1之间浮点数。
anchor锚选项,同 pack 布局,默认值为 NW
bordermode如果设置为 INSIDE,组件内部的大小和位置是相对的,不包括边框;

如果是OUTSIDE,组件的外部大小是相对的,包括边框。

可以使用常量INSIDEOUTSIDE,也可以使用字符串形式 insideoutside

方法
方法作用
place_slaves()以列表方式返回本组件的所有子组件对象。
place_configure(option=value)place 布局管理器设置属性,使用属性(option)= 取值(value)方式设置
place_propagate(boolean)设置为 True 表示父组件的几何大小由子组件决定(默认值),反之则无关。
place_info()返回 place 提供的选项所对应的值。
place_forget()Unpack 组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用place(option, …),将其显示。
place_location(x, y)x, y 为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1) 表示不在其中
size()返回组件所包含的单元格,揭示组件大小。

示例
import tkinter as tk
root = tk.Tk()
root.title('窗口标题')
root.geometry("300x100+630+80")

btn1 = tk.Button(root)
btn1['text'] = '点击'
btn1.place(relx=0.2, x=10, y=20, relwidth=0.2, relheight=0.5)

btn2 = tk.Button(root)
btn2['text'] = '退出'
btn2.place(relx=0.2, x=70, y=20, relwidth=0.2, relheight=0.5)

btn3 = tk.Button(root)
btn3['text'] = '取消'
btn3.place(relx=0.2, x=130, y=20, relwidth=0.2, relheight=0.5)

root.mainloop()

在这里插入图片描述


Tkinter 基本控件

tkinter 中,每个组件都是一个类,创建某个组件其实就是将这个类实例化。

在实例化的过程中,可以通过构造函数给组件设置一些属性,同时还必须给该组件指定一个父容器,意即该组件放置何处。

最后,还需要给组件设置一个几何管理器(布局管理器),解决了放哪里的问题,还需要解决怎么放的问题,而布局管理器就是解决怎么放问题的,即设置子组件在父容器中的放置位置。

ttkTk 8.5 版本开始加入的模块。在之前,我们学习的小控件外观看起来都很陈旧过时,编写的界面会比较丑陋。而 ttk 模块的出现正是为了解决这个问题,它使小控件的外观更接近于系统平台所特定的外观,不仅如此,它还能支持主题的定制,使我们能更简便的改进界面的美观程度。

如果是使用 from tkinter import * 方式导包,则只需在其下增加 from tkinter.ttk import * 即可应用 ttk 风格。使用 ttk 模块后,小控件外观会产生差别。

如使用其他方式导包,则需指定 ttk 模块控件


控件

控件tk 是否支持ttk 是否支持是否在下方给出示意图例
ButtontkttkT
CheckbuttontkttkT
EntrytkttkT
FrametkttkT
LabeltkttkT
LabelFrametkttkT
MenubuttontkttkT
PanedWindowtkttkF
RadiobuttontkttkT
ScaletkttkT
ScrollbartkttkF
ComboboxttkF
NotebookttkF
import tkinter as tk
from tkinter import ttk

class GUI:

    def __init__(self):
        self.root = tk.Tk()
        self.root.title('title')
        self.root.geometry("400x480+500+250")
        # self.root.geometry("300x200+500+250")
        self.interface()

    def interface(self):
        """"界面编写位置"""
        btntk = tk.Button(self.root, text="Button tk").pack()
        btnttk = tk.ttk.Button(self.root, text="Button ttk").pack()

        chkbtntk = tk.Checkbutton(self.root, text='Checkbutton tk').pack()
        chkbtnttk = ttk.Checkbutton(self.root, text='Checkbutton ttk').pack()

        entrytk = tk.Entry(self.root, textvariable='Entry tk')
        entrytk.pack()
        entrytk.insert(0, 'Entry tk')
        entryttk = ttk.Entry(self.root, textvariable='entry ttk')
        entryttk.pack()
        entryttk.insert(0, 'Entry ttk')

        frametk = tk.Frame(self.root, bg='khaki', width=150, height=20).pack()
        s = ttk.Style()
        s.configure('new.TFrame', background='red')
        framettk = ttk.Frame(self.root, style='new.TFrame').pack()

        labeltk = tk.Label(self.root, text='Label tk').pack()
        labelttk = ttk.Label(self.root, text='Label ttk').pack()

        labelframetk = tk.LabelFrame(self.root, text="LabelFrame tk").pack()
        tk.Message(labelframetk, text="Today is 14th Aug, 2022.", bg="light blue").pack()
        labelframettk = ttk.LabelFrame(self.root, text="LabelFrame ttk").pack()
        tk.Message(labelframettk, text="Today is 14th Aug, 2022.", bg="light pink").pack()

        Menubuttontk = tk.Menubutton(self.root, text='Menubutton tk')
        Menubuttontk.pack()
        filemenutk = tk.Menu(Menubuttontk, tearoff=False)
        filemenutk.add_checkbutton(label="打开", command=self.callback, selectcolor="yellow")
        filemenutk.add_command(label="保存", command=self.callback)
        filemenutk.add_separator()
        filemenutk.add_command(label="退出", command=self.root.quit)
        Menubuttontk.config(menu=filemenutk)
        Menubuttonttk = ttk.Menubutton(self.root, text='Menubutton ttk')
        Menubuttonttk.pack()
        filemenuttk = tk.Menu(Menubuttontk, tearoff=False)
        filemenuttk.add_checkbutton(label="打开", command=self.callback, selectcolor="blue")
        filemenuttk.add_command(label="保存", command=self.callback)
        filemenuttk.add_separator()
        filemenuttk.add_command(label="退出", command=self.root.quit)
        Menubuttonttk.config(menu=filemenuttk)

        rdbtntk = tk.Radiobutton(self.root, text="Radiobutton tk").pack()
        rdbtnttk = ttk.Radiobutton(self.root, text="Radiobutton ttk").pack()

        scaletk = tk.Scale(self.root, orient='horizonta', from_=0, to=100, length=100).pack()
        scalettk = ttk.Scale(self.root, orient='horizonta', from_=0, to=100, length=100).pack()

    def callback(self):
        print('called back ~')

if __name__ == '__main__':
    gui = GUI()
    gui.root.mainloop()

在这里插入图片描述

样式

在使用 ttk 控件时,会发现它的控件不支持 bgfgborder 这样涉及样式的属性,这是因为它对外观样式进行了重新定义。
ttk 对外观样式的抽象共有三个级别:

  1. 主题
  2. 样式
  3. 状态样式

主题的查询与切换
style = ttk.Style()

stype 的引用方式如上,

  • style.theme_names()
    获取所有支持的主题,比如 ('aqua', 'clam', 'alt', 'default', 'classic')
  • style.theme_use()
    获取当前使用的主题,比如 aqua
  • style.theme_use("classic")
    切换主题

样式与控件状态样式的定制

ttk 中,控件实际上是一个字符串,要改变控件样式,需要指定这个字符串名称,而不是类名,它们的对应关系如下:

类名控件样式名
ButtonTButton
CheckbuttonTCheckbutton
ComboboxTCombobox
EntryTEntry
FrameTFrame
LabelTLabel
LabelFrameTLabelFrame
MenubuttonTMenubutton
NotebookTNotebook
PanedWindowTPanedwindow
ProgressbarHorizontal.TProgressbarVertical.TProgressbar
RadiobuttonTRadiobutton
ScaleHorizontal.TScaleVertical.TScale
ScrollbarHorizontal.TScrollbarVertical.TScrollbar
SeparatorTSeparator
SizegripTSizegrip
TreeviewTreeview

需要注意,在创建新样式时,应当定义 newName.oldName 形式的名称


示例
import tkinter
from tkinter import Tk
from tkinter import ttk

root = Tk()

style = ttk.Style()

# 定义一个全局样式作为默认样式("."表示此样式将应用于顶级窗口及其所有子元素)
style.configure('.', font='Arial 14', foreground='brown', background='yellow')

# 未指定样式时,使用全局默认样式
ttk.Label(root, text='我没有指定样式').pack()

# 定义一个名为danger的新样式(newName.oldName格式)
style.configure('danger.TButton', font='Times 12', foreground='red', padding=1)
ttk.Button(root, text='我使用danger样式',  style='danger.TButton').pack()

# 为小控件的不同状态指定样式
style.map("new_state_style.TButton", foreground=[('pressed', 'red'), ('active', 'blue')])
ttk.Button(text="不同状态不同样式", style="new_state_style.TButton").pack()

# 覆盖Entry的当前主题(即使没有指定样式,也会受到主题更改的影响)
current_theme = style.theme_use()
style.theme_settings(current_theme,
                     {"TEntry": {
                         "configure": {"padding": 10},
                         "map": {"foreground": [("focus", "red")]}}})
val = tkinter.StringVar()
val.set('Entry控件样式')
ttk.Entry(textvariable=val).pack()

root.mainloop()

在这里插入图片描述


封装

基本版

import tkinter as tk
from tkinter import ttk -下拉选择框

class GUI:

    def __init__(self):
        self.root = tk.Tk()
        self.root.title('窗口标题')
        self.root.geometry("400x250+500+250")
        self.interface()

    def interface(self):
        """"界面编写位置"""
        pass

if __name__ == '__main__':
    gui = GUI()
    gui.root.mainloop()

菜单-主菜单、子菜单

?


界面

控件类名称简要说明
Label标签
LabelFrame标签框架带有标签和边框的一个容器,通常用于控件分组
Message消息框类似于标签,但可以自动换行,用于显示多行文本
OptionMenu选项菜单下拉菜单
Spinbox输入控件与Entry类似,但可以指定输入范围值
Menu菜单点菜单按钮后弹出的一个选项列表,用户可以从中选择
Listbox列表框一个选项列表,用户可以从中选择
Scrollbar滚动条对其支持的组件(文本域、画布、列表框、文本框)提供滚动功能
Text多行文本框显示多行文本
Top Level顶级窗口独立存在的窗口

Label

概念

Label 作为一个最常用的控件,主要用实现显示功能,能够展示一些文本或者图片或者文本和图片的组合使用 16


语法

它的语法格式:

Label(父对象, options, ...)
参数含义
父对象表示这个文本框将建立在哪一个窗口内
options可选项,即该按钮的可设置的属性。这些选项可以用键 =值的形式设置,并以逗号分隔
font(,)font=('', 15),表示字体、字号
text标签内容
bg背景色
fg前景色

LabelFrame

示例
def interface(self):
    """"界面编写位置"""
    content = "汉皇重色思倾国,御宇多年求不得。杨家有女初长成,养在深闺人未识。\n" \
              "天生丽质难自弃,一朝选在君王侧。回眸一笑百媚生,六宫粉黛无颜色。"

    lf1 = tk.LabelFrame(self.root, text="LabelFrame Top").pack()
    tk.Label(lf1, text=content, bg="orange").pack()

    lf2 = tk.LabelFrame(self.root, text="LabelFrame Bottom").pack()
    tk.Message(lf2, text=content, bg="light blue").pack()

在这里插入图片描述

Frame

ttk

参考此处 17


OptionMenu

示例
def interface(self):
    """"界面编写位置"""
    LIST = ["选项1", "选项2", "选项3"]
    val = tk.StringVar()
    val.set(list[0])
    # 注意,传入的列表前需要加一个*号,这是表示不定参的传递,
    # 两个*则是表示字典类型的不定参传递
    tk.OptionMenu(self.root, val, *LIST).pack()

在这里插入图片描述

Menubutton

参考这里 18


Spinbox

示例
def interface(self):
    """"界面编写位置"""
    # 指定数字范围
    var_range = tk.StringVar()
    var_range.set(0)
    tk.Spinbox(self.root, textvariable=var_range, from_=-5, to=5).pack()

    # 指定列表范围
    LIST = ["选项1", "选项2", "选项3"]
    tk.Spinbox(self.root, value=LIST).pack()

在这里插入图片描述
在这里插入图片描述

Menu

略, 可参考 19


Listbox

概念

在使用 Tkinter 进行 GUI 编程的过程中,如果需要用户自己进行选择时就可以使用列表框控件。
列表框中的选项可以是多个条目,也可以是单个唯一条目,但常用于多个条目 2021


语法
参数含义
listvariable1. 指向一个 StringVar 类型的变量,该变量存放 Listbox 中所有的项目
2. 在 StringVar 类型的变量中,用空格分隔每个项目,例如 var.set("c c++ java python")
selectbackground1. 指定当某个项目被选中的时候背景颜色,默认值由系统指定
selectborderwidth1. 指定当某个项目被选中的时候边框的宽度
2. 默认是由 selectbackground 指定的颜色填充,没有边框
3. 如果设置了此选项,Listbox 的每一项会相应变大,被选中项为 raised 样式
selectforeground1. 指定当某个项目被选中的时候文本颜色,默认值由系统指定
selectmode1. 决定选择的模式,tk 提供了四种不同的选择模式,分别是 single(单选)、browse(也是单选,但拖动鼠标或通过方向键可以直接改变选项)、multiple(多选)和 extended(也是多选,但需要同时按住 Shift 键或 Ctrl 键或拖拽鼠标实现)。默认是 browse
setgrid指定一个布尔类型的值,决定是否启用网格控制,默认值是 False
takefocus指定该组件是否接受输入焦点(用户可以通过 tab 键将焦点转移上来),默认值是 True
xscrollcommandListbox 组件添加一条水平滚动条,将此选项与 Scrollbar 组件相关联即可。

列表框横向滚动时的回调监听。
yscrollcommandListbox 组件添加一条垂直滚动条,将此选项与 Scrollbar 组件相关联即可。

列表框纵向滚动时的回调监听,该属性的值是一个回调函数。

方法
方法作用
activate(index)将给定索引号对应的选项激活,即文本下方画一条下划线
bbox(index)返回给定索引号对应的选项的边框,返回值是一个以像素为单位的 4 元祖表示边框:(xoffset, yoffset, width, height), xoffsetyoffset 表示距离左上角的偏移位置
curselection()返回一个元组,包含被选中的选项序号(从 0 开始)
delete(first, last=None) 删除参数 firstlast 范围内(包含 firstlast)的所有选项
get(first, last=None)返回一个元组,包含参数 firstlast 范围内(包含 firstlast)的所有选项的文本
index(index)返回与 index 参数相应选项的序号
itemcget(index, option)获得 index 参数指定的项目对应的选项(由 option 参数指定)
itemconfig(index, **options)设置 index 参数指定的项目对应的选项(由可变参数 **option 指定)
nearest(y)返回与给定参数 y 在垂直坐标上最接近的项目的序号
selection_set(first, last=None)设置参数 firstlast 范围内(包含 firstlast)选项为选中状态,使用 selection_includes (序号) 可以判断选项是否被选中。
size()返回 Listbox 组件中选项的数量
xview(*args)该方法用于在水平方向上滚动 Listbox 组件的内容,一般通过绑定 Scollbar 组件的 command 选项来实现。

如果第一个参数是 moveto,则第二个参数表示滚动到指定的位置:0.0 表示最左端,1.0 表示最右端;

如果第一个参数是 scroll,则第二个参数表示滚动的数量,第三个参数表示滚动的单位(可以是 unitspages),例如 xview(scroll, 2, pages`)表示向右滚动二行。
yview(*args)该方法用于在垂直方向上滚动 Listbox 组件的内容,一般通过绑定 Scollbar 组件的 command 选项来实现

示例
browse 选择模式 + 绑定点击事件

参考此处 22

def interface(self):
    """"界面编写位置"""
    self.varListbox = tk.StringVar()
    self.varListbox.set(["Go", "Python", "Java", "Dart", "JavaScript"])
    self.listbox = tk.Listbox(self.root, listvariable=self.varListbox, selectmode=tk.BROWSE)
    self.listbox.pack(padx=10, pady=10)
    self.listbox.bind("<<ListboxSelect>>", self.show)

    self.varLabel = tk.StringVar()
    label = tk.Label(self.root, textvariable=self.varLabel, width=20, height=1, bg='lightblue', fg='red')
    label.pack()

def show(self, event):
    self.varLabel.set(self.listbox.get(self.listbox.curselection()))

在这里插入图片描述

extended 选择模式 + 绑定点击事件

参考此处 2324

def interface(self):
    """"界面编写位置"""
    self.varListbox = tk.StringVar()
    self.varListbox.set(["Go", "Python", "Java", "Dart", "JavaScript"])
    self.listbox = tk.Listbox(self.root, listvariable=self.varListbox, selectmode=tk.EXTENDED)
    self.listbox.pack(padx=10, pady=10)
    self.listbox.bind("<<ListboxSelect>>", self.show)

    self.varLabel = tk.StringVar()
    self.label = tk.Label(self.root, textvariable=self.varLabel, width=20, height=1, bg='lightblue', fg='red')
    self.label.pack()

def show(self, event):
    content = []
    for i in self.listbox.curselection():
        content.append(self.listbox.get(i))
    self.varLabel.set(content)

运行效果如下:


在这里插入图片描述


Scollbar

列表框通常用于数据展示或者作为选项菜单使用。滚动条则是一种辅助的小控件,它通常与列表框或者多行文本框结合使用 21


示例
def interface(self):
    """"界面编写位置"""
    self.varListbox = tk.StringVar()
    self.varListbox.set(["Go", "Python", "Java", "Dart", "JavaScript", "C", "C++", "PHPHPHPHPHPHPHPHPHPHPHP"])

    # 分别创建x方向、y方向的两个滚动条。orient属性设置其滚动方向
    y_bar = tk.Scrollbar(self.root, orient=tk.VERTICAL)
    x_bar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)

    # 创建列表框
    self.listbox = tk.Listbox(self.root,
                               yscrollcommand=y_bar.set,
                               xscrollcommand=x_bar.set,
                               listvariable=self.varListbox,
                               height=5)
    y_bar['command'] = self.listbox.yview
    y_bar.pack(side=tk.RIGHT, fill=tk.Y)
    x_bar['command'] = self.listbox.xview
    x_bar.pack(side=tk.BOTTOM, fill=tk.X)
    self.listbox.pack(anchor=tk.NW, fill=tk.BOTH, expand=tk.YES)

    bt = tk.Button(self.root, text='删除', command=lambda x=self.listbox: x.delete(tk.ACTIVE))    # 使用匿名函数,创建删除函数,点击删除按钮,会删除选项
    bt.pack(side=tk.BOTTOM)

在这里插入图片描述

Button

概念

一个简单的按钮,用来响应用户的一个点击操作。能够与一个函数关联,当按钮被按下时,自动调用该函数。

它的属性可以直接参考标签,事实上按钮就是一个特殊的标签,只不过按钮多出了点击响应的功能。


语法
参数含义
text字符串,按钮的文本内容
activebackground当鼠标放上去时,按钮的背景色
activeforeground当鼠标放上去时,按钮的前景色
bd(bordwidth)单位为像素,默认值为 2 个像素 按钮边框的大小
bg(background)按钮的背景色
command函数名的字符串形式 按钮关联的函数,当按钮被点击时,执行该函数
fg(foreground)按钮的前景色(按钮文本的颜色)
font设置字体,还包含样式和大小
image给按钮设置一张图像,必须是用图像 create 方法产生的
bitmap指定按钮显示一张位图
justifyLEFTCENTERRIGHT显示多行文本的时候,设置不同行之间的对齐方式
padx单位像素 按钮在 x 轴方向上的内边距,是指按钮的内容与按钮边缘的距离
pady单位像素 按钮在 y 轴方向上的内边距
reliefRAISED, SUNKEN, FLAT, RIDGE, SOLID, GROOVE设置控件 3D 效果
stateDISABLEDACTIVENORMAL 设置组件状态。正常 (normal)、激活(active)、禁用(disabled)
underline取值为整数,默认值为 -1默认按钮上的文本都不带下划线。取值就是带下划线的字符串索引,为 0 时,第一个字符带下划线,为 1 时,前两个字符带下划线,以此类推
width单位像素, 按钮的宽度,如未设置此项,其大小以适应按钮的内容(文本或图片的大小)
height单位像素. 按钮的高度,同 width 属性
wraplength取值为整数,默认值 0, 限制按钮每行显示的字符的数量
textvariable指定一个变量名,变量值被转变为字符串在控件上显示。当变量值改变,控件也将自动更新
anchor取值可参考布局中的锚选项 锚选项,控制文本的位置,默认为中心

示例
def interface(self):
    """"界面编写位置"""
    self.Button0 = tk.Button(self.root, text="按钮显示")
    self.Button0.grid(row=0, column=0)

在这里插入图片描述


Entry

概念

所谓的文本框 Entry,通常是指单行的文本框,在 GUI 程序设计中,这是用于输入的最基本控件,我们可以使用它输入或显示单行字符串,自带宽高 25,通常不需要设定高度,但是存在一些方法可以设定其高度和宽度 26
如果所输入的字符串长度大于文本框的宽度,所输入的文字会自动隐藏,造成部分内容无法显示,碰到这种状况时可以使用箭头键移动鼠标光标到看不到的区域。

文本框限定的是单行文字 27,如果想要处理多行文字,需要使用控件中的 Text


语法

它的语法格式:

Entry(父对象, options, ...)
参数含义
父对象表示这个文本框将建立在哪一个窗口内
optionsborderwidth边界宽度,默认是两个像素
bd边界宽度,默认是两个像素
background背景色彩
bg背景色彩
command当用户更改内容时,会自动执行此函数
cursor当鼠标光标移至按钮上时的形状
exportselection如果执行选取时,所选取的字符串会自动输出至剪贴板;

如果想要避免,可以设置 exportselection=0
foreground前景色彩
fg前景色彩
font字形
height高,单位是字符高
highlightbackground当功能按钮获取焦点时的背景颜色
highlightcolor当工人按钮取得焦点时的颜色
justify当有多行文字时,最后一行文字的对齐方式
relief可由此控制文字外框, 默认是 relief=FLAT
selectbackground被选取字符串的背景色彩
selectborderwidth选取字符串时的边界宽度,预设是1
selectfroeground被选取字符串的前景色彩
show显示输入字符。

例如,show=*表示显示星号,常用于输入密码字段
state输入状态。默认是 NORMAL 表示可以输入,DISABLE 则表示无法输入
textvariable文字变量
width宽,单位是字符宽
xscrollcommandX 轴使用滚动条

方法

参考这里 3

方法作用
delete( first, last=None)删除字符的部件,在指标之一,但不包括在最后位置的字符开始。

如果第二个参数被忽略,只有在单个字符的位置被删除。
get()返回当前组件的字符串
icursor(index)在给定索引处的字符之前插入光标。
index(index)移动 entry 的内容,使得给定索引处的字符是最左边的可见字符。

如果文本在 entry 中刚好完全显示,则不起作用。
insert ( index, s )将字符串 s 插入给定索引处的字符之前。
select_adjust(index)此方法用于确保选中的部分包含指定索引处的字符。
select_clear()清除选中的。 如果当前没有选中的,则不起作用。
select_from(index)ANCHOR 索引位置设置为由索引选择的字符位置,并选择该字符。
select_present()如果有选择,则返回 true,否则返回 false
select_range(start, end)在程序控制下设置选择。 选择从开始索引处开始的文本,但不包括结束索引处的字符。 起始位置必须在结束位置之前。
select_to(index)选择从 ANCHOR 位置开始的所有文本,但不包括给定索引处的字符。
xview(index)此方法在将 Entry 链接到水平滚动条时非常有用。
xview_scroll(number, what)用于水平滚动 Entry。参数必须是 UNITS,按字符宽度滚动,或者按页面大小来滚动。数字是从左到右滚动的正数,负数从右到左滚动。

尺寸
  • tk.Entry(root, width)
    Entry 控制元件中的 width 选项设定宽度, 其单位是文字单位,而不是像素。
    一个文字单位等于系统字型中 0 的宽度。
  • tk.Entry().place(width, height)
    place 方法中的 widthheight 选项设定 Entry 控制元件的宽度和高度像素单位
  • tk.Entry().place(ipadx, ipady)
    tk.Entry().grid(ipadx, ipady)
    packgrid 方法中的 ipadxipady 在水平和垂直方向上设定内部填充,可以间接设定 Entry 控制元件的宽度和高度。

在这里插入图片描述
Entry 的实际宽度是 2 * ipadx + 预设 Entry 宽度,类似地,Entry 的实际宽度是 2 * ipady + 预设 Entry 高度


示例
def interface(self):
    """"界面编写位置"""
    self.Entry0 = tk.Entry(self.root)
    self.Entry0.grid(row=0, column=0)

在这里插入图片描述


Text

概念

多行文字区域,可用来收集(或显示)用户输入的文字,可以编辑文本格式,改变文本框的宽高 25
也可以当网页浏览器使用,插入文字、图片、组件等。


语法

Text 组件创建方法为 Text(父组件,参数)
可以使用默认的参数来创建一个 Text 组件,比如 text = tk.Text(root),或者,text=Text(root, width=12, height=5),宽 12 个字符,高 5 行字符。


参数含义
autoseparators是否自动插入一个分隔符,默认 True
backgroundbg组件的背景颜色
borderwidthbd组件的边框宽度
cursor鼠标光标样式
exportselection选中的文本是否可以被复制到剪贴板,默认 True
font组件的默认文本字体
foregroundfg组件的前景色,字体颜色
heightText 组件的高度,单位是:行
highlightabckground组件没有焦点时的高亮边框的颜色
highlightcolor组件有焦点时的高亮边框的颜色
highlightthickness高亮边框的宽度
insertbackground插入光标的颜色,默认为 black
insertborderwidth插入光标的边框宽度 ,默认为 0
insertontime插入光标闪烁的间隔时间,单位:毫秒
insertwidth光标的宽度,默认为 2 像素
maxundo最大的‘撤销’操作次数,默认为 0,为 -1 表示不限制
padx水平方向上内容与边框之间的间距,默认为 1
pady垂直方向上内容与边框之间的间距,默认为 1
relief组件边框样式
selectbackground选中文本的背景颜色
selectborderwidth选中文本的边框宽度
selectforeground选中文本的字体颜色
setgrid是否启用网格控制,默认为 False
spacing1每一行的上面间距,如有折行,只在第一行起作用 28
spacing2折行之间的行间距 28
spacing3每一行的下面间距,如有折行,只在最后一行起作用 28
state组件的状态 NORMALDISABLED
tabs定义按 Tab 键的移动距离
takefocus是否可以使用 Tab 键将焦点转移到本组件
undo开启 undo / redo 功能
width组件的宽度,单位是:字符数
wrap决定文本长度超过组件宽度如何换行:

NONE 不换行
CHAR 按字符来换行,中英文都一样。
WORD 按单词自动换行,保证英文单词做为一个整体来换行,对中文没有什么意义。
xscrollcommand与滚动条组件在水平方向相关联
yscrollcommand与滚动条组件在垂直方向相关联

方法
方法作用
delete语法是 delete(开始位置,结束位置),如果只有1个参数,就只删除一个字符; 有2个参数,则删除一段文本 28
get获取所选的字符内容,语法是 get(开始位置,结果位置)。位置可以直接用行、列格式,也可以用位置表达式来表示 28
INSERT等价于字符串 insert,表示当前光标的位, 可以将字符插入到指定的位置,语法是 insert(插入位置,插入字符)

举例 28
insert(END, '汽车'),在字符串末尾插入字符
insert(INSERT, ‘汽车'),在光标处插入字符
insert(2.3, '飞机'),在第2行、第3列处插入字符

注:行从 1 开始起步,列从 0 列开始起步。位置表达式的用法参考这里 28
CURRENT等价于字符串 current,当前鼠标所在的位置
END等价于字符串 end,表示文本最末的位置
line.column直接指定行列位置,如 1.0,表示第一行第一列,注意,行号从 1 开始,列号从 0 开始。
line.end指定行末位置,如 1.end,表示第一行结尾的位置
+ n chars1.0+5c,表示在第一行第一列的位置向右移动五个字符的位置
linestartcurrent linestart,表示当前光标所在行的行首位置
Mark主要用来控制位置
Tags主要用来改变内容的样式

标签

Text 组件跟 EntryLable 等组件在字体方面可不一样,其它字体只要设置一种字体,而 Text 组件可以为同一组件内的不同的字符设置为不同的字体,颜色,大小。
当我们为 Text 组件内的一两个字符或一段字符取一个名字时,这个名字就是一个标签。说白了,标签就是你选定一段字符的名称。

书签是 行.列 位置的另一个名称,是一个位置;
标签是一段选定的字符的名称,是一段字符。

可以为 Text 组件创建标签,也可以删除标签,也可以为标签设置一下,如为标签设置字体,颜色等,设置成功后,这个标签代表的一段字符就会表现出设置好的字体和颜色。


内置标签

系统内有一个内置的标签,那就是 SELSEL 就是你用鼠标选中的一段字符的标签。

当我们用鼠标选定文本框中的某一段文本时,这一段文本就是 SEL 标签的范围,默认情况是,选定的文本是蓝色背景,白色文字,我们可以用代码为 SEL 标签改变一为红色背景,白色文字,同时也可以改变字体大小等。见示例。


外设标签

下面是标签的一些常用的方法:

方法作用
tag_add(标签名,开始位置,结束位置)为开始位置和结束位置之间的字符创建一个标签名。
tag_config(标签名,参数……)为标签设置字体,颜色等等各种参数。
tag_delete(标签名)标签被删除,与此标签相关的设置显示效果都自动取消
tag_remove(标签名)标签被删除,但此标签相关的设置显示效果还起作用。
tag_bind(标签名,绑定事件,调用的函数)设置标签后,这个标签还可以绑定事件。比如,写一个网址,你点击它就可以用默认的浏览器打开它。

Checkbutton

概念

一个多选框组件。主要给用户提供多个选项的选中功能。


语法
Checkbutton(master,option,...)

方法

参考这里 3

方法作用
deselect()清除单选按钮的状态。
flash()在激活状态颜色和正常颜色之间闪烁几次单选按钮,但保持它开始时的状态。
invoke()可以调用此方法来获得与用户单击单选按钮以更改其状态时发生的操作相同的操作。
invoke()设置单选按钮为选中。
select()设置单选按钮为选中。

示例
def interface(self):
    """"界面编写位置"""
    self.Checkbutton01 = tk.Checkbutton(self.root, text="名称")
    self.Checkbutton01.grid(row=0, column=2)

在这里插入图片描述


Radiobutton

概念

单选按钮,即在同一组内只能有一个按钮被选中,每当选中组内的一个按钮时,其它的按钮自动改为非选中态,与其他控件不同的是,它有组的概念。


语法
Radiobutton(parent, option, ... )

方法

参考这里 3

方法作用
deselect()清除单选按钮的状态。

示例
def interface(self):
    """"界面编写位置"""
    self.varRbtn = tk.StringVar()
    self.Rbtn1 = tk.Radiobutton(self.root, text="Option 1", variable=self.varRbtn, value='Beijing', command=self.show).pack()
    self.Rbtn2 = tk.Radiobutton(self.root, text="Option 2", variable=self.varRbtn, value='Shanghai', command=self.show).pack()
    self.Rbtn3 = tk.Radiobutton(self.root, text="Option 3", variable=self.varRbtn, value='Guangzhou', command=self.show).pack()

    self.varLabel = tk.StringVar()
    label = tk.Label(self.root, textvariable=self.varLabel, width=20, height=1, bg='lightblue', fg='red')
    label.pack()

def show(self):
    self.varLabel.set(self.varRbtn.get())

在这里插入图片描述
在这里插入图片描述


Combobox

参考这里 2930


概念

Combobox 是下拉框控件,可以看成是单行文本框组件 Entry 和 下拉菜单组建构成的。所以在文本框里,可以输入,在菜单里也可以选择。
当点击下拉按钮之后,会弹出下拉列表,用户选择相应的选项后,下拉列表会收起,用户选择的选项会出现在输入框中。
下拉框控件和列表框控件非常类似,不过只显示为一个输入框,更省窗口空间 30

Combobox 不是定义在 tkinter 中的控件,而是定义在 ttk 中的一个控件。
Combobox 不是继承的 Widget 类,而是继承了 Entry 类,因此可以把 Combobox 当成是 Entry 类的扩展。


语法

它的语法格式:

Combobox(父对象, options, ...)
参数含义
父对象表示这个文本框将建立在哪一个窗口内
optionsheight高度,下拉显示的条目数量,默认值是20。

如果超过这个默认值,会自动出现滚动条。如果项目数没有到 height 设定的值,会显示实际的行数。也就是说不会出现空白行,比如行数是 10,就不会出现 10 个待选项 + 10 个空白行的情况,下拉列表只显示 10 个待选项。
width定义输入框的宽度。默认值是 20

注意,这个参数只能调整输入框的宽度,不能调整下拉按钮的宽度。在计算真个下拉框控件的宽度的时候,要把这两个数值加在一起。
state设置状态 normal (可选可输入)、readonly (只可选)、 disabled (禁止输入选择)
cursor鼠标位于Combobox控件时的形状, 比如 arrow, circle, cross, plus
font(,)font=('', 15),表示字体、字号
textvariable通过 StringVar 设置可改变的值
value以元组方式存在,设置下拉框的选项。该参数可以动态调整。
justify输入框中的文字对齐方式。只有当文本内容的长度小于输入框框的长度才有效。默认是左对齐 tk.LEFT

其他的2个对齐方式是 tk.CENTER(居中)和 tk.RIGHT(右对齐)。
postcommand下拉列表弹出前的回调函数。用于动态改变下拉列表内容,即即时输出选择前的选项值。

要即时得到选择后的选项值,要借助一个虚拟事件 <<ComboboxSelected>> 即时得到 combobox 选择后的值 31
takefocus设置能否使用Tab键获得输入焦点。默认是True。
stylettk 中的控件,没有了设置背景色、前景色等属性,所有的这些都通过style来设置。
validate validatecommand设置验证回调函数,用以验证输入框中的内容是否符合要求。

方法

参考这里 30

方法作用
current(newindex=None)没有任何参数,返回输入框中的内容在下拉列表中的行号。

如果输入框中的内容不与下拉列表中的任何一项相匹配,返回 -1;

如果有参数,返回索引所代表的行的内容,该选项会出现在输入框中。不返回任何参数。
set(value)设置输入框中的文本。调用该函数后,在输入框显示 value 指定的值。注意,value 可以不是下拉列表中的值。

我们可以用绑定的变量,如 var.set (文本值) 来设置 combobox 组件上的 textvariable (输入文本)。
此外,还有另外一种方法 com1.set (文本值) 达到的效果是一样的。

示例
def interface(self):
    """"界面编写位置"""
    cb = tk.ttk.Combobox(master=self.root,
                         height=10,
                         width=20,
                         state='normal',
                         cursor='arrow',
                         font=('', 15),
                         value=('python', 'java', 'C', 'C++'))
    # 若是选项很多,可以使用独立在Combobox()外来处理,如下所示:
    # combobox
    # cb['values'] = ('python', 'java', 'C', 'C++')
    cb.pack(padx=5, pady=10)

在这里插入图片描述


Scale

概念

一个滑块控件。用于在一个范围内,拖动它改变值的大小,例如音量条。


语法

它的语法格式:

Scale(父对象, options, ...)
参数含义
父对象表示这个文本框将建立在哪一个窗口内
optionsfrom_设置最小值
to设置最大值
tickinterval设置刻度
length设置滑块的长度,单位为像素
示例

更多的示例可以参考这里 32

def interface(self):
    """"界面编写位置"""
    self.var = tk.IntVar()
    self.scale = tk.Scale(self.root, orient='horizonta', variable=self.var,
                          from_=0, to=200, tickinterval=50, length=200, command=self.show).pack()

    self.varLabel = tk.StringVar()
    label = tk.Label(self.root, textvariable=self.varLabel, width=20, height=1, bg='lightblue', fg='red')
    label.pack()

def show(self, event):
    self.varLabel.set(self.var.get())

在这里插入图片描述

PanedWindow

概念

PanedWindow 是一个窗口布局管理的插件,可以包含一个或者多个子控件。用户可以用鼠标移动上面的分割线来改变每个子控件的大小 33

PanedWindow 可以用来创建2格或者3格的布局。


示例

下面的例子演示了如何使用 tkPanedWindow 插件创建窗格:


二窗格
def interface(self):
    """"界面编写位置"""
    panedwindowtk = tk.PanedWindow(orient=tk.VERTICAL)
    panedwindowtk.pack(fill=tk.BOTH, expand=1)
    top = tk.Label(panedwindowtk, text="top pane", bg='yellow', width=10, height=5)
    panedwindowtk.add(top)
    bottom = tk.Label(panedwindowtk, text="bottom pane", bg='light blue', width=10, height=5)
    panedwindowtk.add(bottom)

在这里插入图片描述
在这里插入图片描述

三窗格
def interface(self):
    """"界面编写位置"""
    panedwindowtk = tk.PanedWindow()
    panedwindowtk.pack(fill=tk.BOTH, expand=1)

    left = tk.Label(panedwindowtk, text="left pane", bg='yellow', width=10, height=5)
    panedwindowtk.add(left)

    panedwindow2tk = tk.PanedWindow(panedwindowtk, orient=tk.VERTICAL)
    panedwindowtk.add(panedwindow2tk)

    top = tk.Label(panedwindow2tk, text="top pane", bg='light blue', width=5, height=5)
    panedwindow2tk.add(top)

    bottom = tk.Label(panedwindow2tk, text="bottom pane", bg='pink', width=5, height=5)
    panedwindow2tk.add(bottom)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Top Level

概念

实际上我们的根窗口就是一个顶级窗口。
它是独立存在的一个窗口,当我们需要编写多窗口程序或者自定义对话框时,就需要使用它。

既然根窗口也是一个顶级窗口,那么顶级窗口的属性和方法,根窗口同样具有。


示例
def interface(self):
    """"界面编写位置"""
    self.btn = tk.Button(self.root, text="打开窗口", command=self.onclick).pack()

def onclick(self):
    window = tk.Toplevel()
    window.geometry('200x100+500+250')
    label = tk.Label(window, text="我是新窗口").pack()

    window.transient(self.root)
    # 设置它所依托的父窗口
    window.mainloop()
    # 必须调用mainloop,打开一个新窗口后,需要进入新窗口的事件循环

在这里插入图片描述

def interface(self):
    btnOpen = tk.Button(self.root, text="打开窗口", command=self.onclick).pack()

def onclick(self):
    window = tk.Toplevel()
    window.geometry('200x100+500+250')
    window.title('我是新窗口')
    btnClick = tk.Button(window, text="点击", command=lambda: self.test(window)).pack()

    window.mainloop()

def test(self, window):
    window.iconify()
    window.deiconify()

在这里插入图片描述


如果要使该窗口保持在所有其他窗口之上 3435

root.attributes("-topmost", True)
# 其中root是您的顶级或Tk。 不要忘记"topmost"前面的 -

Progressbar

概念

进度条控件


语法

它的语法格式:

Progressbar(父对象, options, ...)
参数含义
optionsmode有两个值可选。indeterminate 表示来回反弹样式,determinate 表示步进样式
length设置进度条的长度

方法
方法说明
.start()开始自动增长模式
.stop()停止自动增长模式
.step(amount)默认起始步长 (?)
.grid_forget()
.place_forget()
取决于 Progressbar 的位置置放使用的是 grid 布局方法还是 place 布局方法,选择相应的 forget 方法来删除 Progressbar 控件 36

详情查看 gridplace 布局管理方法。

示例
def interface(self):
    """"界面编写位置"""
    self.progress = ttk.Progressbar(self.root, mode='indeterminate', length=100)
    # 创建进度条控件
    self.progress.pack(pady=10, padx=10)
    # 启动进度条控件

    self.progress2 = ttk.Progressbar(self.root, mode='determinate', length=100)
    self.progress2.pack(pady=10, padx=10)

    tk.Button(self.root, text='Start', command=self.start).pack()
    tk.Button(self.root, text='Stop', command=self.stop).pack()
    tk.Button(self.root, text='Delete', command=self.delete).pack()

def start(self):
    self.progress.start(interval=100)
    self.progress2.start(interval=20)

def stop(self):
    self.progress.stop()
    self.progress2.stop()

def delete(self):
    self.progress.pack_forget()
    self.progress2.pack_forget()

在这里插入图片描述


Notebook

概念

选项卡控件


示例
def interface(self):
    """"界面编写位置"""
    notebook = tk.ttk.Notebook(self.root)
    
    page1 = tk.Frame(notebook, background="light yellow")
    tk.Label(page1, text="这是 tab1 的界面").pack()
    page2 = tk.Frame(notebook, background="light pink")
    tk.Label(page2, text="这是 tab2 的界面").pack()

    notebook.add(page1, text="Tab1")
    notebook.add(page2, text="Tab2")
    notebook.pack(fill=tk.BOTH, expand="yes")

在这里插入图片描述

Treeview

概念

该小部件有助于可视化并允许在项目的层次结构上进行导航。它可以显示层次结构中每个项目的多个功能。它可以像在 Windows 资源管理器中一样构建类似于用户界面的树形视图 9


语法

它的语法格式:

tv = ttk.Treeview(root, height=20, selectmode = 'browse',show= 'tree')

delete(*tree.get_children())| 删除节点 37

参数说明
父对象表示这个文本框将建立在哪一个窗口内
columns列标识符的列表,用于指定列数及其名称。
displaycolumns列标识符(符号或整数索引)的列表,用于指定显示哪些数据列出及其出现的顺序,或字符串 “#all"
height指定应可见的行数。注意,请求的宽度由列宽度的总和确定。
padding指定窗口小部件的内部填充。填充是最多四个长度规范的列表。
selectmode控制内置类绑定如何管理选择。

extendedbrowsenone
如果设置为 extended (默认),则一次将仅选择一个项目。
如果为 none,则选择不会更改。
show包含零个或多个以下值的列表,指定要显示树的哪些元素。
- tree:在第0列中显示树标签。
- headings:显示标题行。

默认值为 tree headings,即显示所有元素。
注意:即使未指定 show='tree,列 #0 始终引用树列。

事件
示例
简单示例
def interface(self):
    """"界面编写位置"""
    self.tree = tk.ttk.Treeview(self.root, show='tree')
    # 监听self.tree中item被选中的事件
    self.tree.bind("<<TreeviewSelect>>", self.item_select)

    # 第一个参数为父节点, 第二个为此项在父节点中的位置(父节点为空时,默认为根节点)
    item1 = self.tree.insert("", 0, text="广东省")
    # 在第一个节点中插入如下子节点
    self.tree.insert(item1, 0, text="广州市")
    self.tree.insert(item1, 1, text="深圳市")

    item2 = self.tree.insert("", 1, text="湖北省")
    self.tree.insert(item2, 0, text="武汉市")
    self.tree.insert(item2, 1, text="宜宾市")

    self.tree.pack()

def item_select(self, event):
    for select in self.tree.selection():
        print(self.tree.item(select, "text"))

在这里插入图片描述

复杂示例
def interface(self):
    """"界面编写位置"""
    # show用于禁止列顶部标签。columns用于设置每一列的列标识字符串
    self.tree = ttk.Treeview(self.root, show='headings', columns=['0', '1', '2'])

    # 监听tree中item被选中的事件
    self.tree.bind("<<TreeviewSelect>>", self.item_select)

    # 设置表头名称
    self.tree.heading(0, text='序号', command=lambda: self.head_onclick('序号'))
    self.tree.heading(1, text='姓名', command=lambda: self.head_onclick('姓名'))
    self.tree.heading(2, text='年龄', command=lambda: self.head_onclick('年龄'))

    # 设置每列中元素的样式
    self.tree.column(0, anchor='center')
    self.tree.column(1, anchor='center')
    self.tree.column(2, anchor='center')

    # "end" 表示往父节点的最后一个位置插入
    item1 = self.tree.insert("", "end", values=("1", "赵二", "19"))
    item1 = self.tree.insert("", "end", values=("2", "张三", "20"))
    item1 = self.tree.insert("", "end", values=("3", "李四", "22"))
    item1 = self.tree.insert("", "end", values=("4", "王五", "18"))

    self.tree.place(relx=0.01, rely=0.1, width=500, height=500)

def item_select(self, event):
    for select in self.tree.selection():
        print(self.tree.item(select, "values"))

def head_onclick(self, type):
    print(type)

在这里插入图片描述


Scrollbar

参考这里 3839


概念

滚动条部件中包含滑块 slider, 前后两个箭头 arrow1, arrow2, 滑块槽 trough (分前后两头滑块槽 trough1 / trough2),滑块的大小及位置代表可见的部份占全部内容的比例及位置 (0.0 ~ 1.0)

Scrollbar (滚动条) 允许查看另一个小部件的所有部分,其内容通常大于可用空间。
Tkinter Scrollbar 小部件不属于任何其他小部件,例如 TextListbox
相反,Scrollbar 是一个独立的小部件。

Tkinter Scrollbar 小部件基本上提供了滑动控制器,用于实现垂直滚动小部件,如 ListboxCanvasText
使用 Scrollbar 小部件,还可以尝试在条目小部件上创建水平滚动条。
当滚动条设置为垂直时,Scrollbar 用于滚动内容以垂直查看整个内容。 水平滚动条用于水平滚动内容。


语法

Scrollbar() 语法将用于获取具有以下属性的滚动条 masteroption / options

创建 Scrollbar 的语法如下:

w = scrollbar(master, option/options, ...)

参数说明如下:

参数说明
MasterTkinter 滚动条的这个 master 属性只代表父窗口。
option / optionsScrollbar 的选项 / 选项属性将具有滚动条小部件常用的选项列表。这些选项 / 选项主要用作键值对,以逗号分隔。

常用选项列表:

参数说明
activebackground当鼠标/光标点在滚动条 / 滑块上时,Scrollbaractivebackground 选项用于为滑块 / 滚动条 / 箭头 / 箭头 / 光标符号着色。
activereliefactive 时的滑块花边样式,内定为 RAISED
Bg当鼠标 / 光标点实际上不在滚动条 / 滑块上时,Scrollbarbg 选项对于更改滚动条 / 箭头 / 光标点的背景非常有帮助。
bd用于设置围绕整个槽的周边的 3d 边框的宽度,以及滑块和鼠标点 / 箭头 / 光标点上的 3d 效果的宽度。默认情况下,槽的每个角落周围 / 旁边都没有边框。连同在滑块和箭头 / 光标点周围有 2 个像素的边框一起。
command每次滚动条 / 滑块移动时根据需要调用的过程。
cursor使光标在滚动条位于鼠标 / 光标点下方时出现。
elementborderwidth用于调整滑块和箭头/光标周围的边框宽度。默认情况下,elementborderwidth 的值为 1。可以根据需要 / 需要使用 elementborderwidth 选项添加任何边框宽度。
highlightbackground用于在滚动条 / 滑块没有任何焦点时突出显示颜色。
highlightcolor用于当鼠标点 / 滚动条 / 滑块有焦点时高亮的焦点颜色。
highlightthickness用于设置高亮的粗细,但默认情况下,高亮粗细值设置为 1。您可以将值设置为 0 以抑制焦点高亮的显示。
jump控制用户拖动 / 拖动滑块时发生的情况。默认情况下,跳转选项的 0 值会导致每个小滑块拖动的回调命令。如果跳转选项值设置为值 1,则如果用户没有释放鼠标 / 光标按钮,则不会调用回调。
orient用于将方向设置为水平/垂直。就像 orient=HORIZONTALorient =VERTICAL
repeatDelay控制在滑块重复向特定方向移动之前,按钮 1 在槽中按下的时间。默认情况下,重复延迟 (repeatdelay=300)300,单位为毫秒。
repeatInterval重复间隔,以毫秒为单位重复按下滑块槽,内定 100ms。
takefocus用于通过滚动条小部件切换焦点,但如果您不想要此功能/行为,可以将其设置为值 0。
troughcolor滑块槽的颜色。
width用于设置滚动条/滑块的宽度( x 尺寸用于垂直,y 尺寸用于水平)。默认情况下,宽度值为 16 ( width=16 )。

用法

滚动条部件的方法:

方法说明
activate(element=None)返回鼠标所在零件,slider / arrow1 / arrow2 / (其他), 或者设置聚焦在该零件
delta(dx, dy)如同鼠标移动 (dx, dy), 返回目前滑块相对移动量,该值在 -1.0 ~ +1.0
fraction(x, y)返回相对于 (x, y) 位置的滑块位置,0.0 ~ +1.0
get()返回目前滑块位置的前缘 a 与后缘 b, (a, b), 0.0 ~ +1.0
identify(x, y)返回 (x, y) 所在的零件,slider / arrow1 / arrow2 / trough1 / trough12 / (其他)
set(first, last)要带有滚动条的主部件,其 xscrollcommnad / yscrollcommand 设为本方法,本方法的参数同 get 方法返回的结果同意义

滚动条部件的回调:

方法说明
command (tk.SCROLL, -1, tk.UINTS)滚动条前移一小单位
command (tk.SCROLL, 1, tk.UINTS)滚动条后移一小单位
command (tk.SCROLL, -1, tk.PAGES)滚动条前移一小页面
command (tk.SCROLL, 1, tk.PAGES)滚动条后移一小页面
command (tk.MOVETO, f)滚动条移到相对位置 f: 0.0 ~ +1.0

设置主部件与滚动条部件的连接:

  • 主部件的 xscrollcommand / yscrollcommand 为滚动条部件的 set 方法;
  • 水平 / 垂直滚动条部件的 command 为主部件的 xview / yview 方法;
  • 水平 / 垂直滚动条部件的 grid 方法选项 sticky, 应该要设置为 EW / NS;

注:移动滚动条并不会移动滚动其主部件


示例

首先,创建一个 Scrollbar 小部件。
其次,将 Scrollbar 与可滚动的小部件链接起来。

下面展示了如何使用 ttk.Scrollbar 构造函数创建 Scrollbar 小部件:

from tkinter import ttk
scrollbar = ttk.Scrollbar(
    container,						# 滚动条所在的窗口 或 Frame
    orient='vertical',				# 指定滚动条是需要水平滚动还是垂直滚动
    command=widget.yview			# 参数允许滚动条小部件与滚动小部件进行通信
)

Scrollbar 小部件还需要向 Scrollbar 反馈当前可见的整个内容区域的百分比。
每个 Scrollbar 小部件都有一个 yscrollcommand 和 / 或 xscrollcommand 选项。
可以将 scrollbar.set 方法分配给它:

widget['yscrollcommand`] = scrollbar.set

Text

Text 小部件是几种可滚动小部件之一。

关于组件如何绑定一个水平滚动条,Text 组件有点不一样,因为它是可以自动换行的,如果自动换行,那水平滚动条绑定成功也没有什么用。
这时,wrap 参数就显得很重要了,加入 wrap=NONE 后,文本只要没有硬换行符,超过 Text 都不会换行,这时,超长看不到的文本就可以通过水平滚动条来查看了。
以分别将 wrap=WORDwrap=CHAR 代替 wrap=NONE 测试一下,这2种情况都会换行,绑定水平滚动条就没有什么意义了 28

下面的程序演示了一个简单的用户界面,它由 TextScrollbar 小部件组成 28

垂直 scrollbar
    def interface(self):
        """"界面编写位置"""
        text = tk.Text(self.root, width=50, height=5)
        text.grid(row=0, column=0, sticky='ew')
        text.insert('insert', '1'*1000)

        scrollbar = ttk.Scrollbar(self.root, orient='vertical', command=text.yview)
        scrollbar.grid(row=0, column=1, sticky='ns')

        text['yscrollcommand'] = scrollbar.set

运行效果如下:

在这里插入图片描述


水平 scrollbar

参考这里 40

def interface(self):
    """"界面编写位置"""
    # 创建文本框text,设置宽度、文本显示的行数,以及 wrap 类型
    text = tk.Text(self.root, width=20, height=5, wrap=NONE)
    text.insert(INSERT, '1' * 1000)
    text.grid(row=0, column=2)

    x_scrollbar = tk.Scrollbar(self.root, orient='horizontal', command=text.xview)
    x_scrollbar.grid(row=1, column=2, sticky='we')

    text['xscrollcommand'] = x_scrollbar.set

或者,

def interface(self):
    """"界面编写位置"""
    # 创建水平方向的滚动条
    x_scrollbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
    x_scrollbar.grid(row=1, column=2, sticky=tk.E + tk.W)

    # 创建文本框text,设置宽度、文本显示的行数,以及 wrap 类型
    text = tk.Text(self.root, width=20, height=5, wrap=NONE, xscrollcommand=x_scrollbar.set)
    text.insert(INSERT, '1' * 1000)
    text.grid(row=0, column=2)
    x_scrollbar['command'] = text.xview

运行效果如下:
在这里插入图片描述
又或者,

def interface(self):
    """"界面编写位置"""
    # 创建文本框text,设置宽度、文本显示的行数,以及 wrap 类型
    text = tk.Text(self.root, wrap=NONE)
    text.insert(INSERT, '1' * 1000)
    text.grid(sticky=W+E+S+N)
    # scrollbar向4边扩展

    # 创建水平方向的滚动条
    x_scrollbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
    x_scrollbar.grid(row=50, columnspan=10, sticky=W + E)
    # src向东西扩展

    # 滚动设置相互绑定
    text.config(xscrollcommand=x_scrollbar.set)
    x_scrollbar.config(command=text.xview)

运行效果如下,

在这里插入图片描述


Listbox

参考这里 3941

需要同时配置 ListboxScrollbar 以使他们能正确地耦合在一起。


垂直 scrollbar
  • yscrollcommand 回调设置为 Scrollbar 的 setyscrollcommand 是由滚动条控制的可滚动控件的选项,用于与垂直滚动条进行通信。
  • 设定 ScrollbarcommandListboxyview。当用户移动 Scrollbar 的滑块时,它将使用适当的参数调用 yview 方法。
def interface(self):
    """"界面编写位置"""
    font = ('Courier New', 16, 'bold')

    elements = ('List for House', 'List for Friend', 'List for Cash', 'List for Car',
                'List for Motorcycle', 'List for Boat', 'List for Airplane')

    # 创建垂直方向的滚动条
    y_scrollbar = tk.Scrollbar(self.root, orient=tk.VERTICAL)
    y_scrollbar.pack(side='right', fill='y')

    # 创建选项框
    list_box = tk.Listbox(self.root, font=font, selectmode=tk.EXTENDED,
                          width=20, height=3, activestyle='dotbox',
                          yscrollcommand=y_scrollbar.set)
    list_box.insert(tk.END, *elements)
    list_box.pack(side='top', fill='both')

    y_scrollbar.config(command=list_box.yview)

运行效果如下:


在这里插入图片描述

水平 scrollbar
def interface(self):
    """"界面编写位置"""
    font = ('Courier New', 16, 'bold')

    elements = ('List for House', 'List for Friend', 'List for Cash', 'List for Car',
                'List for Motorcycle', 'List for Boat', 'List for Airplane')

    # 创建水平方向的滚动条
    x_scrollbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
    x_scrollbar.grid(row=1, column=0, sticky=tk.E + tk.W)

    # 创建选项框
    list_box = tk.Listbox(self.root, font=font, selectmode=tk.EXTENDED,
                          width=15, height=5, activestyle='dotbox',
                          xscrollcommand=x_scrollbar.set)
    list_box.insert(tk.END, *elements)
    list_box.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)

    x_scrollbar['command'] = list_box.xview

运行效果如下:


在这里插入图片描述

水平 & 垂直 scrollbar
def interface(self):
    """"界面编写位置"""
    font = ('Courier New', 16, 'bold')

    elements = ('List for House', 'List for Friend', 'List for Cash', 'List for Car',
                'List for Motorcycle', 'List for Boat', 'List for Airplane')

    # 创建水平 & 垂直方向的滚动条
    x_scrollbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
    x_scrollbar.grid(row=1, column=0, sticky=tk.E + tk.W)
    y_scrollbar = tk.Scrollbar(self.root, orient=tk.VERTICAL)
    y_scrollbar.grid(row=0, column=1, sticky=tk.N + tk.S)

    # 创建选项框
    list_box = tk.Listbox(self.root, font=font, selectmode=tk.EXTENDED,
                          width=15, height=5, activestyle='dotbox',
                          xscrollcommand=x_scrollbar.set,
                          yscrollcommand=y_scrollbar.set)
    list_box.insert(tk.END, *elements)
    list_box.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)

    x_scrollbar['command'] = list_box.xview
    y_scrollbar['command'] = list_box.yview

运行效果如下:


在这里插入图片描述


Combobox
水平 scrollbar
def interface(self):
    """"界面编写位置"""
    self.cb = tk.ttk.Combobox(master=self.root,
                              height=10,
                              width=20,
                              state='normal',
                              cursor='arrow',
                              font=('', 15),
                              value=('中国', '美国', '英国',
                                     '全宇宙第一强国,谁也无法超越的超级大国,你谁呀?')
                              )
    self.cb.pack(padx=5, pady=10)

    scr2 = ttk.Scrollbar(orient=tk.HORIZONTAL)
    # 水平滚动条
    scr2.pack(fill=tk.X, padx=10, pady=(0, 10))

    self.cb.config(xscrollcommand=scr2.set)
    # combobox绑定滚动条设置
    scr2.config(command=self.cb.xview)

运行效果如下,

在这里插入图片描述


ScrolledText

参考这里 3842


概念

为了更方便,Tkinter 提供了 ScrolledText 小部件,它与链接到垂直滚动条的文本小部件执行相同的操作。


用法

要使用 ScrolledText 小部件,需要从 tkinter.scrolledtext 模块导入 ScrolledText 类。从技术上讲,ScrolledText 类继承自 Text 类。ScrolledText 小部件使用插入在容器和 Text 小部件之间的 Frame 小部件来保存 Scrollbar 小部件。因此,ScrolledText 具有与 Text 小部件相同的属性和方法。 此外,包括 packgridplace 在内的几何管理器方法仅限于 Frame


示例
示例 1
def interface(self):
    """"界面编写位置"""
    from tkinter.scrolledtext import ScrolledText
    
    st = ScrolledText(self.root, wrap=WORD, width=10, height=5)
    st.insert(INSERT, '1' * 500)
    st.pack(fill=tk.X, side=tk.TOP, expand=True)

运行效果如下:
在这里插入图片描述


示例 2
def interface(self):
    """"界面编写位置"""
    from tkinter import scrolledtext

    # 创建文本框text,设置宽度100,high不是高度,是文本显示的行数设置为3行
    e4 = tk.Text(self.root, width=20, height=5)
    e4.insert(INSERT, '1' * 1000)
    e4.grid(row=0, column=1, sticky=S + W + E + N)
    # 创建滚动条
    scroll = tk.Scrollbar(orient="vertical", command=e4.yview)

    # 将滚动条填充
    e4.config(yscrollcommand=scroll.set)
    # 将滚动条与文本框关联
    # scroll['command']=e4.yview
    scroll.grid(row=0, column=2, sticky=S + W + E + N)

运行效果如下:
在这里插入图片描述


对话框

分类简要说明
messagebox消息对话框
filedialog文件对话框
colorchooser颜色选择对话框

messagebox
示例
from tkinter import *
from tkinter import messagebox

root = Tk()
root.title("主窗口")								# 设置窗口标题

result = messagebox.askokcancel("标题", "这是内容", parent=root)  
# parent指定依托的父窗口,若不指定,默认为根窗口
messagebox.askquestion("标题", "这是question窗口")
messagebox.askretrycancel("标题", "这是retry cancel窗口")
messagebox.showerror("标题", "这是error窗口")
messagebox.showinfo("标题", "这是info窗口")
messagebox.showwarning("标题", "这是warning窗口")

root.mainloop()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

filedialog

参考这里 4344

参数含义
title设置文件对话框的标题
initialdir设置默认打开的路径
filetypes文件类型筛选。它的值是一个列表,列表中的元素必须是一个二元元组。元组的第一个元素是类型名称,第二个是类型后缀名。

文件
示例
from tkinter import *
from tkinter import filedialog

def onclick():
    file_name = filedialog.askopenfilename(
        title="Open File", initialdir="/Users/xueshanzhang/Downloads",
        filetypes=[("PNG", ".png"), ("PDF", "pdf")])
    print('Open ', file_name)

def save_file():
    file_name = filedialog.asksaveasfilename(
        title="Save File", initialdir="/Users/xueshanzhang/Downloads")
    print('Save as ', file_name)

root = Tk()
Button(root, text="Browse", command=onclick).pack()
Button(root, text="Save", command=save_file).pack()

root.mainloop()

在这里插入图片描述

文件夹
示例
from tkinter import *
from tkinter import filedialog

root = Tk()
root.geometry('700x150+400+300')
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

def onclick():
    # get a directory path by user
    filepath=filedialog.askdirectory(
        initialdir=r"F:\python\pythonProject",
        title="Open Directory"
    )
    label = Label(root, text=filepath, font=('italic 14'))
    label.pack(pady=20)

Button(root, text='select directory', command=onclick).pack()

root.mainloop()

在这里插入图片描述


colorchooser
示例
from tkinter import *
from tkinter import colorchooser

def onclick():
    color = colorchooser.askcolor()
    # 返回值是一个元组,第一个元素是RGB色值元组,第二个是对应的16进制色值
    print('color', color)
    # color((173, 255, 0), '#adff00')

root = Tk()
Button(root, text="Choose Color", command=onclick).pack()

root.mainloop()

在这里插入图片描述


画布

参考这里 4546


概念

canvas 的中文意思就是 画布。在 GUI 中,canvas 是一个非常基础的概念,基本上任何跟 GUI 相关的编程语言、库、框架等,都会有 canvas,只要搞懂了canvas 是什么,就一通百通了。

首先,通俗地解释一下什么是 canvas 。就像画油画一样,得先准备一张画布,然后再在这张画布上进行创作,你可以在画布上画任何你想画的东西,直线、圆、椭圆等。
而在 tkinter 中,canvas 就是类似的作用。提供给你一张 “画布”,你可以在上面 “画” 任何基础图形,也可以 “画” 其他控件。


语法

它的语法格式 Canvas(master, cnf={}, **kw)

想画画,通常要选择一个指定大小的画布,canvas 可以通过属性 widthheight来选择 canvas 的尺寸。

参数含义
width指定 canvas 的宽度。
height指定 canvas 的高度。
bg指定 canvas 的背景颜色。

示例
from tkinter import *
from tkinter.constants import RIGHT, LEFT, X, Y, BOTH

root = Tk()
root.title('Canvas')
width, height = 300, 200
root.geometry(f'{width}x{height}')

cav = Canvas(root, width=width, height=height, bg='lightblue')
cav.pack()

root.mainloop()

可以看到,生成了一张和主窗口一样尺寸的蓝色画布。

在这里插入图片描述

方法

方法作用
cursor指定鼠标的显示样式,当鼠标落在画布区域时。样式的值是 arrow, watch, cross’
relief指定边框样式,默认样式为 flat ,样式的种类有 flat, groove, raised, ridge, solid, sunken
create_line(*args, **kw)画直线,args 参数为 x1, y1 , … , xn , yn 坐标值;

kw 参数为其他属性;
fill 用来填充直线的颜色;
outline 外围轮廓的颜色;
width 为线宽
create_oval(*args, **kw)画椭圆,args 参数为 x1, y1, x2, y2;坐标 (x1,y1), (x2,y2) 指定一个矩形 (正方形) 的左上角和右下角。圆或椭圆就在这个矩形内部。

kw 参数为其他属性,如 fill, outline, width
create_rectangle(*args, **kw)画矩形,args 参数为 x1, y1, x2, y2; 坐标 (x1,y1),(x2,y2) 指定一个矩形 (正方形) 的左上角和右下角。

kw 参数为其他属性,如fill, outline, width
create_polygon( *args, **kw)画多边形,args 参数为 x1, y1, … , xn , yn 坐标值。
kw 参数为其他属性,fill 用来设置直线的颜色;
create_arc(*args, **kw)画弧线,args 参数为 x1, y1, x2, y2 坐标值

kw 参数为其他属性, start 表示起始弧度,extent 表示结束弧度。

根据初中的几何知识,圆弧是由射线绕它的端点旋转,在旋转过程中射线上的点会形成一条狐。
create_text(*args, **kw)显示文字, args 参数为 x1, y1 , x2, y2 坐标值。
kw 参数为其他属性,如 fill, outline, width, font
create_image(*args, **kw)显示图片
move让图形动起来
scale缩放item,语法为 scale(self,xoffset,yoffset,xscale,yscale),其计算公式为 (coords - offset)*scale + offset
tag_bind使用 tag_bind 来绑定 item 与事件,绑定 item 与事件,只有点击到矩形的边框时才会触发事件。

示例

参考这里 45


事件

添加命令

命令绑定的缺陷是,只有 Button 和一小部分控件支持。
功能单一。命令只能绑定到鼠标左键单击和空格键点击事件,无法实现焦点、鼠标滚轮、快捷键响应等等丰富的交互情况。

在不需要给出参数的事件中,
简单举例如下,

import tkinter as tk

def callback():
    print("被点击了")

root = tk.Tk()
tk.Button(root, text='Click', command=callback).pack()

root.mainloop()

在这里插入图片描述

而在需要给出参数的事件中,举例如下:

  1. 可以使用 lambda 表达式;
import tkinter as tk

def callback(args):
    print("被点击了", args)

root = tk.Tk()
tk.Button(root, text='单击', command=lambda: callback("按钮")).pack()

root.mainloop()

在这里插入图片描述

  1. 可以使用经过封装的 command;
import tkinter as tk

class Command:
    def __init__(self, func, *args):
        self.func = func
        self.args = args

    def __call__(self):
        self.func(*self.args)

def callback(args):
    print("被点击了", args)

root = tk.Tk()
tk.Button(root, text='单击', command=Command(callback, "按钮")).pack()

root.mainloop()

在这里插入图片描述


绑定事件

所谓事件,就是在用户按下一个键或点击鼠标时,应用程序需要做出的反应。简单说就是对外部刺激做出的反应。

当窗口小控件中注册的事件发生时,会回调关联的处理函数,并将事件对象的实例作为参数传递到这个处理函数中 47


事件类型
类型名称描述
36ActivateThe state option of a widget changes from inactive to active.
4ButtonOne mouse button is pressed
5ButtonReleaseOne mouse button is released
22ConfigureThe size of the widget is changed
37DeactivateThe state option of a widget change from active to inactive.
17DestroyA widget is being destroyed.
7EnterThe mouse pointer is moved into a visible part of a widget.
12ExposeSome part of the widget or application is visible after having been covered up by another window.
9FocusInThe input focus was moved into a widget.
10FocusOutThe input focus was moved out of a widget.
2KeyPressA key is pressed.
3KeyReleaseA key is released.
8LeaveThe mouse pointer is moved out of a widget.
19MapA widget is being placed on a container e.g., calling the pack() or grid() method.
6MotionThe mouse pointer is moved entirely within a widget.
38MouseWheelThe user moved the mouse wheel up or down.
18UnmapA widget is being unmapped and is no longer visible, for example when calling the grid_remove() method on the widget.
15VisibilityAt least some part of the application window becomes visible on the screen.

鼠标事件

常用的几个鼠标事件,

事件含义
<Button-1>鼠标左击事件
<Button-2>鼠标滚轮点击
<Button-3>鼠标右击事件
<Double-Button-1>鼠标左双击事件
<Triple-Button-1>鼠标左三击事件

关于事件回调传参 之前的命令回调我们都是通过 lambda 表达式传参,这里的事件回调也一样,只是稍微有一点区别:

def callback(event, a, b):
# 修改回调函数,添加a、b两个参数
    print(a, b)
    print("EventType=", event.type)
    
frame.bind("<Button-1>", lambda event: callback(event, 1, 2))
# 注册回调时,在lambda表示中需要定义event参数

键盘事件
import tkinter as tk

root = tk.Tk()
tk.Label(root, text='按键').pack()


def callback(event):
    print("EventType=", event.type)
    print("keysym=", event.keysym)


frame = tk.Frame(root, bg='khaki', width=100, height=80)
frame.pack()
root.bind("<KeyPress-a>", callback)  # a 键
root.bind("<KeyPress-F1>", callback)  # F1 键
root.bind("<Control-Alt-a>", callback)  # Ctrl + Alt + a 键

root.mainloop()

手动模拟事件

有时候我们需要用代码模拟生成一个事件,发送给监听者,而不是通过操作事件源产生事件。

tkinter 中所有的 widget 都包含一个公共方法 event_generate, 这个方法就是用来产生相应的事件的。

event_generate("<<Copy>>")

要想查看这些内置的事件,需要查看 Tk / tcl 的文档,tkinter 只是对 Tk / tcl 的封装,因此 tkinter 的文档并不是非常全面。


事件属性
属性含义
char键盘事件,按键的字符
delta鼠标滚动事件,鼠标滚动的距离
heightwidth仅用于 Configure 事件,即当控件形状发生变化之后的宽度和高度.相当于SizeChanged 事件
keycode键盘事件,按键码
keysymkeysym_num按键事件
num鼠标事件,鼠标按键码,1 为左键,2 为中建,3 为右键
serial相当于 EventID
state用来表示修饰键的状态,即 ctrl, shift, alt 等修饰键的状态
time事件发生的时间
type事件的类型
widget事件源控件
xyx_rooty_root鼠标事件中鼠标的位置。x_rooty_root 为绝对坐标,xy 为相对坐标。

绑定级别

事件有三种绑定级别,实际开发中选择合适的一种即可:

  1. 实例绑定
    将事件绑定到一个特定的控件实例上。如 鼠标事件 绑定到 Frame 实例上。
frame.bind("<Button-1>", callback)
  1. 类级绑定
    可以将事件绑定到类的所有窗口小控件上。典型使用如下,所有 Entry 控件都将绑定到事件,该事件将调用名为 paste 的函数,类级绑定须慎用,以免造成不可预知的问题。
my_entry.bind_class('Entry''<Control-V>',paste)
  1. 应用程序级绑定
    只要应用程序的任何一个窗口处于焦点,事件发生时回调函数都会被调用。
root.bind_all('<F1>',show_help)

只要应用程序处于焦点,按 F1 键将始终触发 show_help 函数回调。


取消绑定

事件被注册后,是可以取消的,三种级别绑定的取消方法如下:

  1. entry.unbind('<Alt-Shift-5>')
  2. root.unbind_all('<F1>')
  3. root.unbind_class('Entry', '<KeyPress-Del>')

Tkinter自定义控件


Tkinter面向对象范式

几乎所有的GUI程序中,都天生的适合运用面向对象思维开发。在GUI程序中使用面向过程的范式,则存在一些缺陷,这也是为什么C语言不适合开发大型GUI程序的原因:

  1. 需要定义大量全局变量;
  2. 需要在调用代码之前定义相关的函数;
  3. 最严重的是代码不可重用;

OOP (Object Oriented Programming 面向对象程序设计) 实际上是一种代码组织方式,它将焦点转移到我们想要操作的对象上,而不是操纵它们所需的逻辑。这与面向过程编程形成对比,面向过程编程将程序视为一个逻辑过程,它接受输入,处理并产生一些输出。

OOP 提供了一些好处,例如数据抽象,封装,继承和多态。此外,OOP 为程序提供了清晰的模块化结构。代码修改和维护很容易,因为可以在不修改现有对象的情况下创建新对象。


聚合式

通常在 Python 中写 Tkinter 界面程序时,很多人会使用这种聚合式的写法,实际上这并不是真正纯粹的面向对象的 GUI 写法,但 tkinter 本身也仅仅是对过程式的 tcl 库的封装,继承小控件并不能真正去重写控件的表现行为,因此是否继承也显得无关紧要,但是在类似 Qt 这种库中则不然。

下面提供一个编码示例:

import tkinter as tk

class App:
    def __init__(self, root):
        self.root = root
        self.set_window()
        self.create_top()
        self.create_body()
        self.create_bottom()

    # 设置窗口
    def set_window(self):
        self.root.title("测试")
        self.root.resizable(False, False)

    # 创建顶部
    def create_top(self):
        tk.Label(self.root, text="Top").pack()

    # 创建主体
    def create_body(self):
        self.input = tk.StringVar()
        tk.Entry(self.root, textvariable=self.input).pack()

    # 创建底部
    def create_bottom(self):
        tk.Button(self.root, text="Bottom", command=self.onclick).pack()

    # 按钮回调函数
    def onclick(self):
        print(self.input.get())

if __name__ == "__main__":
    root = tk.Tk()
    App(root)
    root.mainloop()

继承式

通过继承不能改变控件的表现行为,但是继承式的写法,仍然会让代码更简洁,逻辑更清晰,在其他的面向对象的 GUI 库中,这是一种常用的写法。

下面是示例:

import tkinter as tk


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.set_window()
        self.create_top()
        self.create_body()
        self.create_bottom()

    # 设置窗口
    def set_window(self):
        self.title("测试")
        self.resizable(False, False)

    # 创建顶部
    def create_top(self):
        tk.Label(self, text="Top").pack()

    # 创建主体
    def create_body(self):
        self.input = tk.StringVar()
        tk.Entry(self, textvariable=self.input).pack()

    # 创建底部
    def create_bottom(self):
        tk.Button(self, text="Bottom", command=self.onclick).pack()

    # 按钮回调函数
    def onclick(self):
        print(self.input.get())


if __name__ == "__main__":
    app = App()
    app.mainloop()


参考链接

%todo:


  1. python之Tkinter使用详解 ↩︎

  2. TkDocs ↩︎

  3. Tkinter从入门到实战详解 ↩︎ ↩︎ ↩︎ ↩︎

  4. Tkinter列表框和组合框控件详解 ↩︎

  5. Python | GUI | Tkinter - 1. 基本控件 ↩︎

  6. Python | GUI | Tkinter - 2. 组件使用 ↩︎

  7. Python | GUI | Tkinter - 3. 多窗体 ↩︎

  8. Python | GUI | Tkinter - 4. 多线程的暂停和继续以及文件间调用 ↩︎

  9. Python GUI应用程序中的分层树视图(代码示例) ↩︎ ↩︎

  10. Tcl Developer Xchange ↩︎

  11. Tcl/Tk Insight ↩︎

  12. Tcl 编程/简介 ↩︎

  13. Tcl Files ↩︎

  14. 为什么很多Python开发者写GUI不用Tkinter,而要选择PyQt和wxPython或其他? ↩︎

  15. 3.1 高级控件学习 ↩︎

  16. Python3 Tkinter 实例教学 (六)标签Label 颜色设置 ↩︎

  17. 《tkinter实用教程五》tkinter ttk.Frame控件 ↩︎

  18. Tkinter 组件详解(十四):Menubutton ↩︎

  19. Tkinter菜单Menu的使用示例 ↩︎

  20. Python tkinter Listbox 用法與範例 ↩︎

  21. Tkinter列表框和组合框控件详解 ↩︎ ↩︎

  22. How to assign a command or callback to a tkinter listbox [duplicate] ↩︎

  23. Tkinter python(图形开发界面) ↩︎

  24. Python tkinter Listbox 用法與範例 ↩︎

  25. Tkinter 学习笔记:如何用get()方法获取 Text() 和 Entry()文本框的内容 ↩︎ ↩︎

  26. 如何設定 Tkinter 文字輸入控制元件的高度和寬度 ↩︎

  27. Python之tkinter 文本框Entry的基本应用 ↩︎

  28. 强大的tkinter的多行文本框组件Text ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  29. Python之tkinter 组合框 Combobox ↩︎

  30. Python GUI开发之Tkinter基础篇14:Combobox组件 ↩︎ ↩︎ ↩︎

  31. tkinter.ttk组件combobox讲解 ↩︎

  32. Python tkinter – 第12章 Scale属性 ↩︎

  33. Python Tkinter PanedWindow 控件 ↩︎

  34. python-如何使Tkinter窗口跳到最前面? ↩︎

  35. python tkinter窗口弹出置顶的方法 ↩︎

  36. How i can hide a Progressbar()? ↩︎

  37. 【python】如何使用Tkinter清除整個Treeview ↩︎

  38. Python编程实例-Tkinter GUI编程-Scrollbar与ScrolledText ↩︎ ↩︎

  39. Tkinter (17) 滚动条部件 Scrollbar ↩︎ ↩︎

  40. The horizontal scrollbar didn’t work in Tkinter ↩︎

  41. Tkinter 教程-滚动条 ↩︎

  42. tkinter文本实时更新滚动显示和scrollbar 与grid滚动条能拖拽使用 ↩︎

  43. tkinter filedialog ↩︎

  44. Tkinter askdirectory() Method ↩︎

  45. tkinter-canvas详解 ↩︎ ↩︎

  46. Tkinter Canvas画布控件详解 ↩︎

  47. Tkinter Event Binding ↩︎

  • 4
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,你需要编写一个Python脚本来实现数据转换。这个脚本应该接受两个参数:Excel1的文件路径和Excel2的文件路径。在脚本中,你需要使用pandas库来读取Excel1的数据,并进行必要的转换。然后,你需要将转换后的数据写入Excel2中。 下面是一个可能的Python脚本: ```python import pandas as pd import sys def convert_excel(excel1_path, excel2_path): # 读取Excel1的数据 df = pd.read_excel(excel1_path) # 进行必要的转换 # ... # 将转换后的数据写入Excel2 df.to_excel(excel2_path, index=False) if __name__ == '__main__': excel1_path = sys.argv[1] excel2_path = sys.argv[2] convert_excel(excel1_path, excel2_path) ``` 接下来,你可以使用tkinter来编写一个简单的GUI界面,让用户可以选择Excel1和Excel2的文件路径,然后自动完成数据转换。 下面是一个可能的GUI界面: ```python import tkinter as tk from tkinter import filedialog import os import subprocess class App(tk.Frame): def __init__(self, master=None): super().__init__(master) self.master = master self.pack() self.create_widgets() def create_widgets(self): self.excel1_label = tk.Label(self, text="Excel1:") self.excel1_label.pack() self.excel1_entry = tk.Entry(self) self.excel1_entry.pack() self.excel1_button = tk.Button(self, text="选择文件", command=self.select_excel1) self.excel1_button.pack() self.excel2_label = tk.Label(self, text="Excel2:") self.excel2_label.pack() self.excel2_entry = tk.Entry(self) self.excel2_entry.pack() self.excel2_button = tk.Button(self, text="选择文件", command=self.select_excel2) self.excel2_button.pack() self.convert_button = tk.Button(self, text="转换", command=self.convert) self.convert_button.pack() def select_excel1(self): filename = filedialog.askopenfilename(initialdir=os.getcwd(), title="选择Excel1文件") self.excel1_entry.delete(0, tk.END) self.excel1_entry.insert(0, filename) def select_excel2(self): filename = filedialog.asksaveasfilename(initialdir=os.getcwd(), title="选择Excel2文件") self.excel2_entry.delete(0, tk.END) self.excel2_entry.insert(0, filename) def convert(self): excel1_path = self.excel1_entry.get() excel2_path = self.excel2_entry.get() subprocess.run(["python", "convert.py", excel1_path, excel2_path]) root = tk.Tk() app = App(master=root) app.mainloop() ``` 这个界面包含了两个文本框和两个按钮,分别用于选择Excel1和Excel2的文件路径,以及一个“转换”按钮,用于触发数据转换。当用户点击“转换”按钮时,程序会调用上面编写的Python脚本来完成数据转换。注意,在这个例子中,我们使用了subprocess库来调用Python脚本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值