Tkinter

Tkinter

文档

使用清华镜像源安装:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tkinter

官方文档(python3.6版本)

一本在线电子说明书

一位大神的博客

需求

之前使用pyton编写了一个etl工具,但是使用命令行的形式来操作的,后面感觉这个不是很方便,尝试着做成GUI的形式,因为python有很多种gui库,比如:TkinterwxPythonJythonpyqt5等,一开始也不知道选哪个,后面发现Tkinter是官方自带的比较轻量的,因为容易上手,所以就选择了Tkinter

因为数据的导入导出涉及到业务,所以这里的例子就用另外一种例子来代替。

比如:我们想要一个实现,首先有两个按钮"开始、"暂停",下方有一个"文本框",当点击"开始","开始"按钮被禁用,然后文本框开始输出当前时间的字符串,点击"暂停","文本框"停止输出。再次点击"开始","文本框"继续输出。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import threading
from tkinter import *

THREAD_RUNNING = False # 工作线程是否在运行的标志位
THREAD_GLOBAL_FLAG = True # 线程种的循环标志位
RUN_FLAG = True # 线程中业务循环执行标志位

def increase(text):
    global RUN_FLAG
    global THREAD_GLOBAL_FLAG
    """
    启动一个线程刷新文本框,因为单线程会阻塞tkinter的gui刷新
    :param text:
    :return:
    """
    curr_table_name = "" # 当前表名
    while THREAD_GLOBAL_FLAG:
        while RUN_FLAG:
            text.config(state=NORMAL)
            text.insert('end', "{}
".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
            text.see("end")
            text.config(state=DISABLED)  # 禁止编辑
            time.sleep(1)

def bt_method_start(event, bt_start=None, bt_pause=None, text=None):
    """
    开始按钮点击事件
    :param event:  当前事件
    :param bt_start: 开始按钮对象
    :param bt_pause:  暂停按钮对象
    :param text:  文本框对象
    :return:
    """
    print("bt_method_start")
    global RUN_FLAG
    RUN_FLAG = True
    bt_start['state'] = 'disabled'
    bt_pause['state'] = 'normal'
    # 启动线程
    global THREAD_RUNNING
    if not THREAD_RUNNING:
        THREAD_RUNNING = True
        t = threading.Thread(target=increase, args=(text,))
        t.start()

def bt_method_pause(event, bt_start=None, bt_pause=None, text=None):
    """
    暂停按钮点击事件
    :param event: 当前事件
    :param bt_start: 开始按钮对象
    :param bt_pause: 暂停按钮对象
    :param text: 文本框对象
    :return: 
    """
    print("bt_method_pause")
    global RUN_FLAG
    RUN_FLAG = False
    bt_start['state'] = 'normal'
    bt_pause['state'] = 'disabled'

def on_closing(root):
    """
    关闭窗口事件,在这里做清理工作,线程运行标志位修改
    :param root: 
    :return: 
    """
    print("窗口关闭!")
    global RUN_FLAG
    global THREAD_GLOBAL_FLAG
    RUN_FLAG = False
    THREAD_GLOBAL_FLAG = False
    print(root)
    root.destroy()


def main():
    root = Tk()
    root.title("窗口")
    root.resizable(0, 0)  # 阻止Python GUI的大小调整
    # 注意此处调用lambda没有参数
    # 因为默认的绑定事件等号右边给的是函数名,这种情况没法传递参数,所以使用lambda表达式间接的传递参数
    root.protocol("WM_DELETE_WINDOW", lambda : on_closing(root)) 
    # 窗口居中显示,大小为当前屏幕的50%
    sw = root.winfo_screenwidth()
    sh = root.winfo_screenheight()
    init_width = int(sw * 0.5)
    init_height = int(sh * 0.5)
    init_x = int((sw - init_width)/2)
    init_y = int((sh - init_height)/2)
    root.geometry('{}x{}+{}+{}'.format(init_width, init_height, init_x, init_y))  # 这里的乘是小x
    root.update() # 刷新窗口大小,方便下面获得最新的窗口宽高
    # print(root.winfo_width())
    # print(root.winfo_height())
    # print(root.winfo_screenwidth())
    # print(root.winfo_screenheight())


    # 主框架
    app = Frame(root)
    app.pack()

    # 按钮区域
    frame_button = Frame(app)
    frame_button.pack(side="top")
    # 两个按钮
    bt_start = Button(frame_button, width=12, height=1)
    bt_start["text"] = "同步"
    # bt_start["command"] = bt_method
    # bt_start.bind("<Button-1>", bt_method_start) # 绑定单击事件
    # bt_start.pack(side="left")
    bt_start.grid(column=0, row=0, padx=10, pady=10, ipadx=10, ipady=10)

    bt_pause = Button(frame_button, width=12, height=1)
    bt_pause["text"] = "暂停"
    # bt_pause["command"] = bt_method
    # bt_pause.bind("<Button-1>", bt_method_pause)  # 绑定单击事件
    # bt_pause.pack(side="right")
    bt_pause.grid(column=1, row=0, padx=10, pady=10, ipadx=10, ipady=10)

    # 显示区域
    frame_show = Frame(app)
    frame_show.pack(side="top", padx=5, pady=5 ,ipadx=5, ipady=5)
    # 创建滚动条
    scroll = Scrollbar(frame_show)
    # 将滚动条填充
    scroll.pack(side=RIGHT, fill=Y)  # side是滚动条放置的位置,上下左右。fill是将滚动条沿着y轴填充

    # 显示文字区域
    text_show = Text(frame_show)
    text_show.pack(side=LEFT, fill=Y)
    # 插入初始值
    text_show.insert('end', '你好,欢迎使用!
')
    text_show.config(state=DISABLED)  # 禁止编辑

    # 将滚动条与文本框关联
    scroll.config(command=text_show.yview)  # 将文本框关联到滚动条上,滚动条滑动,文本框跟随滑动
    text_show.config(yscrollcommand=scroll.set)  # 将滚动条关联到文本框

    # 使用 lambda 匿名函数绑定监听控件
    bt_start.bind("<Button-1>", lambda event: bt_method_start(event, bt_start, bt_pause, text_show))  # 绑定单击事件
    bt_pause.bind("<Button-1>", lambda event: bt_method_pause(event, bt_start, bt_pause, text_show))  # 绑定单击事件

    root.mainloop()


if __name__ == '__main__':
    main()

原文地址:https://www.cnblogs.com/bartggg/p/12758925.html