GUI编程之tkinter

tkinter基础

  • Python标准库tkinter是对Tcl/Tk的进一步封装,是一套完整的GUI开发模块的组合或套件,这些模块共同提供了强大的跨平台GUI编程的功能,所有的源码文件位于Python安装目录中lib\tkinter文件夹。

  • tkinter套件中的ttk子模块提供了ComboboxProgressbarTreeview等组件,scrolledtext模块中提供了带滚动条的文本框,messageboxcommondialogdialogcolorchoosersimpledialogfiledialog等模块提供了各种对话框,font模块提供了与字体有关的对象。

  • tkinter常用组件
    GUI编程之tkinter

tkinter开发流程

  • 编写通用代码,例如数据库操作、程序中需要多次调用的函数,这需要在编写代码之间对软件的功能进行分析和整理,最终提炼出通用部分的代码封装成类或函数。
  • 搭建界面,放置菜单、标签、按钮、输入框、选择框等组件,设置组件属性。
  • 编写组件的事件处理代码。
  • 演示实例:
#根据需要导入模块
import tkinter
import tkinter.ttk
import tkinter.messagebox
import tkinter.simpledialog

#这里编写通用代码,或单独放置到另外的模块中再导入

#创建tkinter应用程序主窗口
root = tkinter.Tk()
#此处编写设置窗口属性的代码

#此处编写创建窗口上各种组件的代码
#以及按钮、组合框等交互式组件的事件代码

#启动消息主循环,启动应用程序
root.mainloop()

tkinter实例

1、用户界面登录

import tkinter
import tkinter.messagebox
import os
import os.path

path = os.getenv('temp')
filename = os.path.join(path, 'info.txt')

# 创建应用程序窗口
root = tkinter.Tk()
#定义窗口大小
root['height'] = 140
root['width'] = 200

# 在窗口上创建标签组件
labelName = tkinter.Label(root,
                          text='User Name:',
                          justify=tkinter.RIGHT,
                          anchor = 'e',
                          width=80)
labelName.place(x=10, y=5, width=80, height=20)

# 创建字符串变量和文本框组件,同时设置关联的变量
varName = tkinter.StringVar(root, value='')
entryName = tkinter.Entry(root,
                          width=80,
                          textvariable=varName)
entryName.place(x=100, y=5, width=80, height=20)

labelPwd = tkinter.Label(root,
                         text='User Pwd:',
                         justify=tkinter.RIGHT,
                         anchor = 'e',
                         width=80)
labelPwd.place(x=10, y=30, width=80, height=20)

# 创建密码文本框
varPwd = tkinter.StringVar(root, value='')
entryPwd = tkinter.Entry(root,
                         show='*',
                         width=80,
                         textvariable=varPwd)
entryPwd.place(x=100, y=30, width=80, height=20)

# 尝试自动填写用户名和密码
try:
    with open(filename) as fp:
        n, p = fp.read().strip().split(',')
        varName.set(n)
        varPwd.set(p)
except:
    pass

# 记住我,复选框
rememberMe = tkinter.IntVar(root, value=1)
# 选中时变量值为1,未选中时变量值为0,默认选中
checkRemember = tkinter.Checkbutton(root,
                                    text='Remember me?',
                                    variable=rememberMe,
                                    onvalue=1, offvalue=0)
checkRemember.place(x=30, y=70, width=120, height=20)

# 登录按钮事件处理函数
def login():
    # 获取用户名和密码
    name = entryName.get()
    pwd = entryPwd.get()
    if name=='admin' and pwd=='123456':
        tkinter.messagebox.showinfo(title='恭喜', message='登录成功!')
        if rememberMe.get() == 1:
            # 把登录成功的信息写入临时文件        
            with open(filename, 'w') as fp:
                fp.write(','.join((name,pwd)))
        else:
            try:
                os.remove(filename)
            except:
                pass
    else:
        tkinter.messagebox.showerror('警告', message='用户名或密码错误')
# 创建按钮组件,同时设置按钮事件处理函数
buttonOk = tkinter.Button(root,
                          text='Login',
                          activeforeground='#ff0000',# 按下按钮时文字颜色
                          command=login)
buttonOk.place(x=30, y=100, width=50, height=20)

# 取消按钮的事件处理函数
def cancel():
    #清空用户输入的用户名和密码
    varName.set('')
    varPwd.set('')
buttonCancel = tkinter.Button(root,
                              text='Cancel',
                              command=cancel)
buttonCancel.place(x=90, y=100, width=50, height=20)

#启动消息循环
root.mainloop()

2、电子时钟

import tkinter
import threading
import datetime
import time

app = tkinter.Tk()
app.overrideredirect(True)            # 不显示标题栏
app.attributes('-alpha', 0.9)         # 半透明
app.attributes('-topmost', 1)         # 总是在顶端
app.geometry('130x25+100+100')        # 初始大小与位置

labelDateTime = tkinter.Label(app, width=130)    # 显示日期时间的标签
labelDateTime.pack(fill=tkinter.BOTH, expand=tkinter.YES)
labelDateTime.configure(bg = 'gray')

X = tkinter.IntVar(value=0)           # 记录鼠标左键按下的位置
Y = tkinter.IntVar(value=0)
canMove = tkinter.IntVar(value=0)     # 窗口是否可拖动
still = tkinter.IntVar(value=1)       # 是否仍在运行

def onLeftButtonDown(event):
    app.attributes('-alpha', 0.4)     # 开始拖动时增加透明度
    X.set(event.x)                    # 鼠标左键按下,记录当前位置
    Y.set(event.y)
    canMove.set(1)                    # 并标记窗口可拖动
labelDateTime.bind('<Button-1>', onLeftButtonDown)

def onLeftButtonUp(event):
    app.attributes('-alpha', 0.9)     # 停止拖动时恢复透明度
    canMove.set(0)                    # 鼠标左键抬起,标记窗口不可拖动
labelDateTime.bind('<ButtonRelease-1>', onLeftButtonUp)

def onLeftButtonMove(event):
    if canMove.get()==0:
        return
    newX = app.winfo_x()+(event.x-X.get())
    newY = app.winfo_y()+(event.y-Y.get())
    g = '130x25+'+str(newX)+'+'+str(newY)
    app.geometry(g)                   # 修改窗口的位置
labelDateTime.bind('<B1-Motion>', onLeftButtonMove)

def onRightButtonDown(event):
    still.set(0)
    t.join(0.2)
    app.destroy()                     # 关闭窗口
labelDateTime.bind('<Button-3>', onRightButtonDown)

def nowDateTime():
    while still.get()==1:
        s = str(datetime.datetime.now())[:19]
        labelDateTime['text'] = s     # 显示当前时间
        time.sleep(0.2)
t = threading.Thread(target=nowDateTime)
t.daemon = True
t.start()

app.mainloop()

3、随机提问

import tkinter
import tkinter.messagebox
import random
import threading
import itertools
import time

root = tkinter.Tk()
# 窗口标题
root.title('随机提问')
# 窗口初始大小和位置
root.geometry('260x180+400+300')
# 不允许改变窗口大小
root.resizable(False, False)

# 关闭程序时执行的函数代码,停止滚动显示学生名单
def closeWindow():
    root.flag = False
    time.sleep(0.1)
    root.destroy()
root.protocol('WM_DELETE_WINDOW', closeWindow)

# 模拟学生名单,可以加上数据库访问接口,从数据库中读取学生名单
students = ['张三', '李四', '王五', '赵六', '周七', '钱八']
# 变量,用来控制是否滚动显示学生名单
root.flag = False

def switch():
    root.flag = True
    # 随机打乱学生名单
    t = students[:]
    random.shuffle(t)
    t = itertools.cycle(t)
    
    while root.flag:        
        # 滚动显示
        lbFirst['text'] = lbSecond['text']        
        lbSecond['text'] = lbThird['text']
        lbThird['text'] = next(t)
        
        # 数字可以修改,控制滚动速度
        time.sleep(0.1)
        
def btnStartClick():
    # 每次单击“开始”按钮启动新线程
    t = threading.Thread(target=switch)
    t.start()
    btnStart['state'] = 'disabled'
    btnStop['state'] = 'normal'
btnStart = tkinter.Button(root,
                          text='开始',
                          command=btnStartClick)
btnStart.place(x=30, y=10, width=80, height=20)

def btnStopClick():
    # 单击“停”按钮结束滚动显示
    root.flag = False
    time.sleep(0.3)
    tkinter.messagebox.showinfo('恭喜',
                                '本次中奖:'+lbSecond['text'])
    btnStart['state'] = 'normal'
    btnStop['state'] = 'disabled'
btnStop = tkinter.Button(root,
                         text='停',
                         command=btnStopClick)
btnStop['state'] = 'disabled'
btnStop.place(x=150, y=10, width=80, height=20)

# 用来滚动显示学生名单的3个Label组件
# 可以根据需要进行添加,但要修改上面的线程函数代码
lbFirst = tkinter.Label(root, text='')
lbFirst.place(x=80, y=60, width=100, height=20)

# 红色Label组件,表示中奖名单
lbSecond = tkinter.Label(root, text='')
lbSecond['fg'] = 'red'
lbSecond.place(x=80, y=90, width=100, height=20)

lbThird = tkinter.Label(root, text='')
lbThird.place(x=80, y=120, width=100, height=20)

# 启动tkinter主程序
root.mainloop()
上一篇:python自动化办公(二十 九)TKinter Frame的内部button组件:按钮点击事件不执行command绑定的函数


下一篇:数据分析