【Python入门基础】基于tkinter模块的GUI(一)——TK

图形用户界面

  • GUI是图形用户界面的缩写,Python默认的GUI开发模块是tkinter,是基于Tk的,Tk是一个工具包,提供了跨平台的GUI控件。但Tk并不是最新最好的选择,也没有功能特别强大的GUI控件,事实上,开发GUI应用并不是Python最擅长的工作,如果真的需要使用Python开发GUI应用,wxPython、PyQt、PyGTK等模块都是不错的选择。
  • 基本上使用tkinter来开发GUI应用需要5个步骤:
  1. 导入tkinter模块中我们需要的;
  2. 创建一个顶层窗口对象并用它来承载整个GUI应用;
  3. 在顶层窗口对象上添加GUI组件;
  4. 通过代码将这些GUI组件的功能组织起来;
  5. 进入主事件循环(main loop)
  • GUI应用通常是事件驱动式的,之所以要进入主事件循环是要监听鼠标、键盘等各种时间的发生并执行对应的代码对事件进行处理,因为事件会持续地发生,所以需要在主循环中等待事件发生。另外,Tk为控件地摆放提供了三种布局管理器,通过布局管理器可以对控件进行定位,这三种布局管理器分别是:Placer(开发者提供控件地大小和摆放的位置)、Packer(自动将控件填充到合适的位置)、和Grid(基于网格坐标来摆放控件)。

简单实现按钮Button

import tkinter as tk

class APP:
    def __init__(self,master):
        frame = tk.Frame(master)
        frame.pack(side = tk.LEFT,padx=10,pady=10)
        self.hi_there = tk.Button(frame,text='打招呼',bg='black',fg='white',command=self.say_hi)
        self.hi_there.pack()
    def say_hi(self):
        print('hi')
root = tk.Tk()
app = APP(root)
root.mainloop()

简单实现标签Label

 

from tkinter import *
root = Tk()
def callback():
    var.set('冲')
frame1 = Frame(root)
frame2 = Frame(root)

# 设置字符变量
var = StringVar()
var.set('每日力扣')
textLabel = Label(frame1,
                  textvariable=var,
                  justify=LEFT,
                  padx=10)
textLabel.pack(side=LEFT)
photo = PhotoImage(file='leetcode.gif')
imgLabel = Label(frame1,image=photo)
imgLabel.pack(side=RIGHT)
theButton = Button(frame2,text='加油',command=callback)
theButton.pack()

frame1.pack(padx=10,pady=10)
frame2.pack(padx=10,pady=10)
root.mainloop()

eg.小窗口

import tkinter
import tkinter.messagebox


def main():
    flag = True

    # 修改标签上的文字
    def change_label_text():
        nonlocal flag
        flag = not flag
        color, msg = ('red', '武汉加油')\
            if flag else ('blue', '期待春暖花开')
        label.config(text=msg, fg=color)

    # 确认退出
    def confirm_to_quit():
        if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'):
            top.quit()

    # 创建顶层窗口
    top = tkinter.Tk()
    # 设置窗口大小
    top.geometry('240x160')
    # 设置窗口标题
    top.title('中国加油')
    # 创建标签对象
    label = tkinter.Label(top, text='武汉加油', font='Arial -32', fg='red')
    label.pack(expand=1)
    # 创建一个装按钮的容器
    panel = tkinter.Frame(top)
    # 创建按钮对象
    button1 = tkinter.Button(panel, text='修改', command=change_label_text)
    button1.pack(side='left')
    button2 = tkinter.Button(panel, text='退出', command=confirm_to_quit)
    button2.pack(side='right')
    panel.pack(side='bottom')
    # 开启主事件循环
    tkinter.mainloop()


if __name__ == '__main__':
    main()

运行结果:

说明:‘nonlocal’是Python3中的关键字,Python2.x中没有这个关键字。在Python2.x中闭包只能读取外部函数的变量,而不能改变变量值,而定义位全局变量‘global’很难控制,此时引入了‘nonlocal’,只要在闭包内用nonlocal声明变量,就可以让解释器在外层函数中查找变量名了。来自《Python的闭包和nonlocal》。

 选择框

多选

from tkinter import *
root = Tk()
beauty = ['西施','貂蝉','王昭君','杨玉环']
v = []
for woman in beauty:
    v.append(IntVar())
    b = Checkbutton(root,text=woman,variable=v[-1])
    b.pack(anchor=W)
mainloop()

单选

from tkinter import *
root = Tk()
v = IntVar()
Radiobutton(root,text='One',variable=v,value=1).pack(anchor=W)
Radiobutton(root,text='Two',variable=v,value=2).pack(anchor=W)
Radiobutton(root,text='Three',variable=v,value=3).pack(anchor=W)
mainloop()

from tkinter import *
root = Tk()
languages =[
    ('python',1),
    ('perl',2),
    ('ruby',3),
    ('lua',4)
]
v = IntVar()
v.set(1)
for lan,num in languages:
    b = Radiobutton(root,text=lan,variable=v,value=num,indicatoron=False)
    b.pack(fill=X)
mainloop()

from tkinter import *
root = Tk()
group = LabelFrame(root,text='最好的脚本语言是?',padx=5,pady=5)
group.pack(padx=10,pady=10)
languages =[
    ('python',1),
    ('perl',2),
    ('ruby',3),
    ('lua',4)
]
v = IntVar()
for lan,num in languages:
    b = Radiobutton(group,text=lan,variable=v,value=num)
    b.pack(anchor=W)
mainloop()

 

账号密码界面

from tkinter import *
root = Tk()
Label(root,text='账号:').grid(row=0,column=0)
Label(root,text='密码:').grid(row=1,column=0)

v1 = StringVar()
v2 = StringVar()

e1 = Entry(root,textvariable=v1)
e2 = Entry(root,textvariable=v2,show='*')

e1.grid(row=0,column=1,padx=10,pady=10)
e2.grid(row=1,column=1,padx=10,pady=10)

def show():
    print('账号:%s'%e1.get())
    print('密码:%s' % e2.get())

Button(root,text='芝麻开门',width=10,command=show).grid(row=3,column=0,sticky=W,padx=10,pady=5)
Button(root,text='退出',width=10,command=root.quit).grid(row=3,column=1,sticky=E,padx=10,pady=5)
mainloop()

内容验证

from tkinter import *
master = Tk()
v = StringVar()
def test1():
    if v.get() == 'yes':
        print('True')
        return True
    else:
        print(False)
        e1.delete(0,END)
        return False
def test2():
    print('test2')
    return True
"""
'''
开启Entry对输入文本验证功能。
1、实现该功能,需要通过设置validate、validatecommand和invalidcommand三个选项。 
2、启用验证的开关是validate选项,该选项可以设置以下的值:
    focus:当entry组件获得或者失去焦点的时候验证 
    focusin:当entry组件获得焦点的时候验证 
    focusout:当entry组件失去焦点的时候验证 
    key:当输入框被编辑的时候验证 
    all:当出现上面任何一种情况时候验证 
    none:关闭验证功能。默认设置为该选项
3、validatecommand选项指定一个验证函数,该函数只能返回True或者False表示验证结果,一般情况下验证函数只需要知道输入框中的内容即可,
可以通过Entry组件的get()方法来获得该字符串。
4、invalidcommand选项指定的函数只有在validatecommand的返回值为False的时候才被调用。
'''
'''
validatecommand选项指定一个验证函数,该函数只能返回True或者False表示验证结果
invalidcommand选项指定的函数只有在validatecommand的返回值为False的时候才被调用。
"""
e1 = Entry(master,textvariable=v,validate='focusout',validatecommand=test1,invalidcommand=test2)
e2 = Entry(master)
e1.pack(padx=10,pady=10)
e2.pack(padx=10,pady=10)

mainloop()

加法计算器

from tkinter import *
master = Tk()

frame = Frame(master)
frame.pack(padx=10,pady=10)

v1 = StringVar()
v2 = StringVar()
v3 = StringVar()

def test(content):
    return content.isdigit()

testCMD = master.register(test)
e1 = Entry(frame,width=10,textvariable=v1,validate='key',
           validatecommand=(testCMD,'%P')
           ).grid(row=0,column=0)
Label(frame,text='+').grid(row=0,column=1)
e2 = Entry(frame,width=10,textvariable=v2,validate='key',
           validatecommand=(testCMD,'%P')
           ).grid(row=0,column=2)
Label(frame,text='=').grid(row=0,column=3)
# 默认为 state=NORMAL, 文框状态,分为只读和可写,值为:normal/disabled
e3 = Entry(frame,width=10,textvariable=v3,state='readonly').grid(
    row=0,column=4
)
def calc():
    result = int(v1.get()) + int(v2.get())
    v3.set(str(result))
Button(frame,text="计算结果",command=calc).grid(row=1,column=2,pady=5)
mainloop()

Listbox

Listbox组件根据selectmode选项提供了四种不同的选择模式:SINGLE(单选)、BROWSE(也是单选,但拖动鼠标或者通过方向键可以直接改变选项)、MULTIPLE(多选)和EXTENDED(也是多选,但需要同时按住Shift或者Ctrl或者拖拽鼠标实现)。默认BROWSE。

from tkinter import *
master = Tk()

theLB = Listbox(master,selectmode=SINGLE)
theLB.pack()

for item in ['数学','语文','英语','物理','化学','生物']:
    theLB.insert(END,item)

theButton = Button(master,text='删除',command=lambda x=theLB:x.delete(ACTIVE))
theButton.pack()
mainloop()

为了在某个组件上安装垂直滚动条,需要做两件事:

  1. 设置该组件的yscrollbarcommand选项为Scrollbar组件的set()方法;
  2. 设置Scrollbar组件的command选项为该组件的yview()方法。
from tkinter import *
master = Tk()

sb = Scrollbar(master)
sb.pack(side=RIGHT,fill=Y)

lb = Listbox(master,yscrollcommand=sb.set)

for i in range(1000):
    lb.insert(END,i)
lb.pack(side=LEFT,fill=BOTH)

sb.config(command=lb.yview)
mainloop()

from tkinter import *
master = Tk()

s1 = Scale(master,from_=0,to=42)
s1.pack()

s2 = Scale(master,from_=0,to=200,orient=HORIZONTAL)
s2.pack()

def show():
    print(s1.get(),s2.get())
Button(master,text='获取位置',command=show).pack()

mainloop()

精准刻度

from tkinter import *
master = Tk()

Scale(master,from_=0,to=42,tickinterval=5,resolution=5,length=200).pack()

Scale(master,from_=0,to=200,tickinterval=10,orient=HORIZONTAL,
      length=600).pack()

mainloop()

text中插入按钮和图片

from tkinter import *
master = Tk()

text=Text(master,width=30,height=5)
text.pack()
text.insert(INSERT,'我是一名保安')
text.insert(END,'爱吃小熊饼干')
def show():
    print('点击完成')

b1 = Button(text,text='点击',command=show)
text.window_create(INSERT,window=b1)

mainloop()

from tkinter import *
master = Tk()

text=Text(master,width=100,height=100)
text.pack()
photo = PhotoImage(file='leetcode.gif')
def show():
    text.image_create(END,image=photo)

b1 = Button(text,text='点击',command=show)
text.window_create(INSERT,window=b1)

mainloop()

Tags

Tags(标签)通常用于改变Text组件中内容的样式和功能。可以修改文本的字体、尺寸和颜色。另外,Tags还允许将文本、嵌入的组件和图片于键盘和鼠标等事件相关联。除了user-defined tags(用户自定义的Tags),还有一个预定义的特殊Tags:SEL。SEL或者sel用于表示对应的选中内容(如果有的话)。

可以自定义任意数量的Tags,Tags的名字是由普通字符串组成,可以是除了空白字符外的任何字符。另外,任何文本内容都支持多个Tags描述,任何Tags也可以用于描述多个不同的文本内容。为指定文本添加Tags可以使用tag_add()方法

from tkinter import *
master = Tk()

text=Text(master,width=30,height=5)
text.pack()

text.insert(INSERT,'雅俗共赏雅俗共赏雅俗共赏雅俗共赏')
# 行号.列号
text.tag_add('tag1','1.7','1.12','1.14')
text.tag_config('tag1',background='yellow',foreground='red')

mainloop()

使用tag_raise()和tag_lower()来提高和降低某个Tag的优先级。

from tkinter import *
master = Tk()

text=Text(master,width=30,height=5)
text.pack()

# 行号.列号
text.tag_add('tag1','1.7','1.12','1.14')
text.tag_config('tag1',background='yellow',foreground='red')

text.tag_add('tag2','1.7','1.12','1.14')
text.tag_config('tag2',background='blue')
text.tag_lower('tag2')

text.insert(INSERT,'雅俗共赏雅俗共赏雅俗共赏雅俗共赏',('tag2','tag1'))
mainloop()

超链接

from tkinter import *
import webbrowser
root = Tk()

text=Text(root,width=30,height=5)
text.pack()
text.insert(INSERT,'雅俗共赏雅俗共赏雅俗共赏雅俗共赏')

text.tag_add('link','1.7','1.12','1.14')
text.tag_config('link',background='yellow',foreground='red',
                underline=True)
def show_arrow_cursor(event):
    text.config(cursor='arrow')

def show_xterm_cursor(event):
    text.config(cursor='xterm')

def click(event):
    webbrowser.open('http://www.baidu.com')
text.tag_bind('link','<Enter>',show_arrow_cursor)
text.tag_bind('link','<Leave>',show_xterm_cursor)
text.tag_bind('link','<Button-1>',click)

mainloop()

检查功能

from tkinter import *
import hashlib
root = Tk()

text=Text(root,width=30,height=5)
text.pack()
text.insert(INSERT,'雅俗共赏雅俗共赏雅俗共赏雅俗共赏')

contents = text.get('1.0',END)

def getSig(contents):
    m = hashlib.md5(contents.encode())
    return m.digest()

sig = getSig(contents)

def check():
    contents = text.get('1.0',END)
    if sig!=getSig(contents):
        print('内容发生改变')
    else:
        print('内容未发生改变')
Button(root,text='检查',command=check).pack()

mainloop()

mainloop()

全文搜索

from tkinter import *
import hashlib
root = Tk()

text=Text(root,width=30,height=5)
text.pack()
text.insert(INSERT,'雅俗共赏雅俗共赏雅俗共赏雅俗共赏')

def getIndex(text,index):
    return tuple(map(int,str.split(text.index(index),'.')))
start = '1.0'
while True:
    pos = text.search('俗',start,stopindex=END)
    if not pos:
        break
    print(getIndex(text,pos))
    # 指向下一个字符
    start = pos + '+1c'


mainloop()

撤销

from tkinter import *
import hashlib
root = Tk()
"""
# 默认情况下,每一次完整的操作将会放入栈中。但怎么样算是一次完整的操作呢?
# Tkinter 觉得每次焦点切换、用户按下 Enter 键、删除\插入操作的转换等
# 之前的操作算是一次完整的操作,一次的“撤销”操作就会将所有的内容删除。
# 那我们能不能自定义呢?比如我希望插入一个字符就算一次完整的操作,然后
# 点击“撤销”就去掉一个字符。当然可以!
# 做法就是先将autoseparators 选项设置为 False(因为这个选项是让 
# Tkinter 在认为一次完整的操作结束后自动插入“分隔符”),然后绑定键盘事
# 件,每次有输入就用 edit_separator() 方法人为地插入一个“分隔符”。
"""

text=Text(root,width=30,height=5,undo=True,autoseparator=False)
text.pack()
text.insert(INSERT,'雅俗共赏雅俗共赏雅俗共赏雅俗共赏')

def callback(event):
    text.edit_separator()
text.bind('<Key>',callback)

def show():
    text.edit_undo()
Button(root,text='撤销',command=show).pack()

mainloop()

 

 

 

 

 

 

 

 

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Version: 2.15.0 (2020-09-28) Keil.STM32F4xx_DFP.2.15.0.pack Download Updated Pack to STM32Cube_FW_F4 Firmware Package version V1.25.1 using HAL Drivers V1.7.9. STM32CubeMX integration (Version 6.0.1): Added support for Timebase Source TIMx (FrameworkCubeMX_gpdsc.ftl). Removed non-existent include path. CMSIS Flash Algorithm: Corrected STM32F42xxx_43xxx_OPT Algorithm. CMSIS SVD: Updated STM32F42*.svd, STM32F43*.svd files. CMSIS-Driver: I2C: Corrected 2 byte reception in master mode. MCI: Replaced empty delay loops with _NOP(). SPI: Corrected PowerControl function (to return error if Initialize was not called, to abort active transfer if power off was requested). Updated GetDataCount function to give accurate count in DMA mode. Corrected Control function (abort in DMA mode, software controlled slave select in slave mode, TI Frame Format selection, ignore bus speed for slave mode). Corrected Uninitialize function (to power off the peripheral if it is powered). Corrected SPI3_SCK pin configuration. Corrected DMA MemDataAlignment configuration. USART: Corrected DMA MemDataAlignment configuration. USBD_HS/USBH_HS: OTG_HS ULPI clock disabled in low power if internal PHY is used to enable proper operation of OTG_HS port in FS mode during CPU sleep. CAN/EMAC/USBD/USBH: Removed macros already provided by cmsis_compiler.h. Updated Boards Examples: Migrated CubeMX projects to V6.0.1 and updated config files. Changed variant selection to "MDK-Plus" where possible. Updated all USB Host/Device examples with user templates from MDK-Middleware v7.11.1. Terminating app_main thread with osThreadExit() to avoid endless loop Updated MS Windows UBS driver files.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZoomToday

给作者倒一杯卡布奇诺

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

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

打赏作者

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

抵扣说明:

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

余额充值