Python Tkinter Gui 窗口图标,标签,输入,单复选,文件导入,按钮,日志 等常用组件 基本使用
文章目录
前言
一、窗体设置方法
1.tk类对象的方法
二、常用组件以及公共属性介绍
1.常用组件
2.公共属性
三、常用布局摆放方式
1.grid()–>以行和列(网格)形式对控件进行排列,此种方法使用起来较为灵活,推荐此方法
2.pack()–>按照控件的添加顺序其进行排列,遗憾的是此方法灵活性较差
3.place()–>(x,y)定位摆放,可以指定组件大小以及摆放位置,三个方法中最为灵活的布局方法
四、示例代码
1.打包(exe)后的环境资源访问
2.完整代码
3.运行效果
总结
前言
tkinter是什么?
我们编写的Python代码会调用内置的Tkinter,Tkinter封装了访问Tk的接口;
Tk是一个图形库,支持多个操作系统,使用Tcl语言开发;
Tk会调用操作系统提供的本地GUI接口,完成最终的GUI;
tkinter库简介
python内置的GUI库,只要安装好 Python 环境之后就能 import tkinter 库;
基于Tk工具包,该工具包最初是为TCL设计的,后被应用到多种脚本语言中,使脚本语言可以开发出品质较好的GUI应用,tkinter是用python做的一个调用接口,底层使用C++编写,运行效率上与C++编写的GUI应用相当,但是开发效率远远高于C++;
本文思路:先介绍窗体以及组件的方法和属性,最后附上示例代码供大家参考
一、窗体设置方法
1.tk类对象的方法
Tk类常用方法 |
描述 |
title() |
设置窗体标题 |
iconbitmap() |
设置窗体logo,建议写绝对路径 |
geometry() |
设置窗体大小,单位是像素 |
attributes("-topmost", 1) |
窗体设为置顶 (显示为当前活动窗口) |
protocol('WM_DELETE_WINDOW', lambda: clos_window() |
设置右上角(X)点击事件,退出/关闭窗体 |
destroy() |
直接退出/关闭窗体 |
winfo_screenwidth() |
获取屏幕宽度 |
winfo_screenheight() |
获取屏幕高度 |
mainloop() |
界面循环,即是显示窗体变化 |
二、常用组件以及公共属性介绍
1.常用组件
组件类 |
名称 |
描述 |
Button |
按钮 |
一个简单的按钮,用来执行一个命令或别的操作,类似标签,但提供额外的功能,例如鼠标掠过、按下、释放以及键盘操作/事件。 |
Canvas |
画布 |
组织图形,这个部件可以用来绘制图表和图,创建图形编辑器,实现定制窗口部件,提供绘图功能(直线、椭圆、多边形、矩形) ;可以包含图形或位图 |
Checkbutton |
复选框 |
代表一个变量,它有两个不同的值。点击这个按钮将会在这两个值间切换,一组方框,可以选择其中的任意个 |
Radiobutton |
单选框 |
一组可选框,其中只有一个可被"选中" ,以当前勾选的值为准 |
Entry |
文本框 |
文本输入框,文本输入域 |
Frame |
框架/容器 |
归纳组件,用于模块布局,一个容器窗口部件 |
Label |
标签 |
用来显示文字或图片 |
Listbox |
列表框 |
一个选项列表,用户可以从中选择 |
Menu |
菜单 |
点下菜单按钮后弹出的一个选项列表,用户可以从中选择,菜单条,用来实现下拉和弹出式菜单 |
Menubutton |
菜单按钮 |
用来包含菜单的组件(有下拉式、层叠式等等) |
Scale |
进度条 |
线性“滑块”组件,可设定起始值和结束值,会显示当前位置的精确值 |
Scrollbar |
滚动条 |
对其支持的组件(文本域、画布、列表框、文本框)提供滚动功能 |
Text |
文本域 |
多行文字区域,可用来收集(或显示)用户输入的文字(类似 HTML 中的 textarea) |
ScrolledText |
可滚动文本域 |
常用于日志输出显示 |
Toplevel |
顶级 |
类似框架,但提供一个独立的窗口容器 |
2.公共属性
属性/参数 |
描述 |
master |
父窗口指针/上级容器(如:TK类对象) |
text |
组件标题(部分组件有:Button、Label ....) |
bd |
组件边框的大小,默认为 2 个像素 |
image |
组件上要显示的图片 |
font=('行楷', 15, 'bold') |
字体,大小,加粗 |
fg |
字体颜色 |
bg |
背景颜色 |
height |
高,单位像素 |
width |
宽 |
command |
(Button)绑定处理事件函数,当按钮被点击时,执行该函数 command=function,如需传参( command=lambda: function("参数")) |
三、常用布局摆放方式
1.grid()–>以行和列(网格)形式对控件进行排列,此种方法使用起来较为灵活,推荐此方法
属性/参数 |
描述 |
row |
设置行数 |
rowspan |
设置跨行数量,控件实例所跨的行数,默认为 1 行,通过该参数可以合并一列中多个领近单元格 |
column |
设置列数 |
columnsapn |
设置跨列数量,控件实例所跨的列数,默认为 1 列,通过该参数可以合并一行中多个领近单元格 |
ipadx |
设置组件的内部"左右"的间距,单位为像素(p),或者厘米(c)、英寸(i) |
ipady |
设置组件的内部"上下"的间距,单位为像素(p),或者厘米(c)、英寸(i) |
padx |
设置组件的外部"左右"的间距 ,单位为像素(p),或者厘米(c)、英寸(i) |
pady |
设置组件的外部"上下"的间距,单位为像素(p),或者厘米(c)、英寸(i) |
sticky |
该属性用来设置控件位于单元格那个方位上,参数值和 anchor 相同,若不设置该参数则控件在单元格内居中 |
2.pack()–>按照控件的添加顺序其进行排列,遗憾的是此方法灵活性较差
属性/参数 |
描述 |
side |
设置组件相对与父组件的摆放位置,组件放置在窗口的哪个位置上,参数值 'top','bottom','left','right'。注意,单词小写时需要使用字符串格式,若为大写单词则不必使用字符串格式 |
ipadx |
设置组件的内部"左右"的间距,单位为像素(p),或者厘米(c)、英寸(i) |
ipady |
设置组件的内部"上下"的间距,单位为像素(p),或者厘米(c)、英寸(i) |
padx |
设置组件的外部"左右"的间距 ,单位为像素(p),或者厘米(c)、英寸(i) |
pady |
设置组件的外部"上下"的间距,单位为像素(p),或者厘米(c)、英寸(i) |
3.place()–>(x,y)定位摆放,可以指定组件大小以及摆放位置,三个方法中最为灵活的布局方法
属性/参数 |
描述 |
anchor |
定义控件在窗体内的方位,参数值N/NE/E/SE/S/SW/W/NW 或 CENTER,默认值是 NW |
x、y |
定义控件在根窗体中水平和垂直方向上的起始绝对位置,(单位为像素),绝对定位 |
height、width |
控件自身的高度和宽度(单位为像素),绝对定位 |
relx |
设置距离左上角的水平长度百分比(0-1),相对定位 |
rely |
设置距离左上角的垂直高度百分比 ,相对定位 |
relwidth |
设置组件所占据的宽度百分比 ,相对定位 |
relheight |
设置组件所占据的高度百分比 ,相对定位 |
四、示例代码
1.打包(exe)后的环境资源访问
import os
import sys
""" 判断是否为打包(exe)后的环境 """
if getattr(sys, 'frozen', False):
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
file_path = os.path.join(base_path, "xxxxxxx")
2.完整代码
示例说明:引用了线程不卡顿,滚动文本域实时更新日志,建议复制代码运行仔细观察一下有助于理解
该示例使用了grid()网格布局,输入组件,标签组件,文件选择组件,单选框组件,复选框组件,按钮,滚动文本域,大部分都写了注释哈;
import sys
import time
import tkinter as tk
from tkinter import messagebox
from tkinter.messagebox import askyesno
from tkinter.filedialog import askopenfilename # 文件选择
from tkinter.scrolledtext import ScrolledText
import threading
class TestGui(object):
def __init__(self, init_window_name):
self.file_input_dirs = None # 存放文件地址变量
self.init_window_name = init_window_name
self.init_window_name.title("Python Tkinter 常用组件 - 基本使用") # 设置窗口标题
self.init_window_name.geometry('700x400') # 设置窗口大小
self.init_window_name.iconbitmap('resource/test.ico') # 设置窗体左上角logo,建议写绝对路径
self.init_window_name.attributes("-topmost", 1) # tk界面置顶
""" 点击右上角关闭窗体弹窗事件 """
self.init_window_name.protocol('WM_DELETE_WINDOW', self.clos_window)
""" 组件容器创建 """
self.input_frame = tk.Frame(master=self.init_window_name) # 创建存放文本输入,文件选择组件的容器
self.input_frame.grid(padx=20, pady=5, row=1, column=0, sticky=tk.W) # 外间距20px,上下间距0,1行,0(从0开始)列
self.choose_day_frame = tk.Frame(master=self.init_window_name) # 创建存放单选组件的容器
self.choose_day_frame.grid(padx=20, pady=0, row=2, column=0, sticky=tk.W)
self.choose_number_frame = tk.Frame(master=self.init_window_name) # 创建存放复选组件的容器
self.choose_number_frame.grid(padx=20, pady=0, row=3, column=0, sticky=tk.W)
self.log_frame = tk.Frame(master=self.init_window_name) # 创建存放日志组件的容器
self.log_frame.grid(padx=20, pady=0, row=4, column=0, sticky=tk.W)
self.runs_button_frame = tk.Frame(self.init_window_name) # 创建存放日志组件的容器
self.runs_button_frame.grid(padx=20, pady=0, row=5, column=0, sticky=tk.W)
""" 文本输入,文件选择组件 """
self.file_input_title = tk.Label(self.input_frame, text="输入文件地址", font=('行楷', 15))
self.file_input_title.grid(padx=20, pady=0, row=0, column=0, sticky=tk.W)
self.file_input_entry = tk.Entry(self.input_frame, font=('行楷', 20), width=24)
self.file_input_entry.grid(padx=0, pady=0, row=0, column=1)
self.file_input_button = tk.Button(self.input_frame, text="选择文件", font=('行楷', 15), width=12, fg="white", bg="#1E90FF", command=self.file_input_path)
self.file_input_button.grid(padx=10, pady=0, row=0, column=2, sticky=tk.W)
""" 单选框 - 选择日期 """
self.radio_label = tk.Label(self.choose_day_frame, text="单选框:", font=('行楷', 15))
self.radio_label.grid(padx=20, pady=0, row=0, column=1, sticky=tk.W)
self.choose_day_value = tk.StringVar()
self.date_list = ['2022-10-16', '2022-10-17', '2022-10-18', '2022-10-19']
self.choose_day_value.set(0) # 设置默认值 '0'
# 单选组件参数介绍 text=勾选框文本, variable=赋值对象, value=勾选后的值
self.choose_day_one = tk.Radiobutton(self.choose_day_frame, text=self.date_list[0], variable=self.choose_day_value, value=self.date_list[0], font=('行楷', 12))
self.choose_day_one.grid(padx=12, pady=0, row=0, column=2)
self.choose_day_two = tk.Radiobutton(self.choose_day_frame, text=self.date_list[1], variable=self.choose_day_value, value=self.date_list[1], font=('行楷', 12))
self.choose_day_two.grid(padx=12, pady=0, row=0, column=3)
self.choose_day_three = tk.Radiobutton(self.choose_day_frame, text=self.date_list[2], variable=self.choose_day_value, value=self.date_list[2], font=('行楷', 12))
self.choose_day_three.grid(padx=12, pady=0, row=0, column=4)
self.choose_day_four = tk.Radiobutton(self.choose_day_frame, text=self.date_list[3], variable=self.choose_day_value, value=self.date_list[3], font=('行楷', 12))
self.choose_day_four.grid(padx=12, pady=0, row=0, column=5)
""" 复选框 - 选择数字 """
self.check_label = tk.Label(self.choose_number_frame, text="复选框:", font=('行楷', 15))
self.check_label.grid(padx=20, pady=0, row=0, column=1, sticky=tk.W)
self.choose_number_value_one = tk.IntVar()
self.choose_number_value_one.set(0) # 设置默认值 0
self.choose_number_value_two = tk.IntVar()
self.choose_number_value_two.set(0) # 设置默认值 0
self.choose_number_value_three = tk.IntVar()
self.choose_number_value_three.set(0) # 设置默认值 0
# 复选组件参数介绍 text=勾选框文本, variable=赋值对象, onvalue=勾选后的值, offvalue未勾选的值
self.choose_entry_time_one = tk.Checkbutton(self.choose_number_frame, text='1', variable=self.choose_number_value_one, onvalue=1, offvalue=0, font=('行楷', 12))
self.choose_entry_time_one.grid(padx=12, pady=0, row=0, column=2)
self.choose_entry_time_two = tk.Checkbutton(self.choose_number_frame, text="2", variable=self.choose_number_value_two, onvalue=2, offvalue=0, font=('行楷', 12))
self.choose_entry_time_two.grid(padx=12, pady=0, row=0, column=3)
self.choose_entry_time_three = tk.Checkbutton(self.choose_number_frame, text="3", variable=self.choose_number_value_three, onvalue=3, offvalue=0, font=('行楷', 12))
self.choose_entry_time_three.grid(padx=12, pady=0, row=0, column=4)
""" 日志框 """
self.run_log = ScrolledText(self.log_frame, font=('楷体', 13), width=69, height=14)
self.run_log.grid(padx=20, pady=5, row=0, column=0)
""" 操作按钮 """
self.start_run1 = tk.Button(self.runs_button_frame, text='参数打印', font=('行楷', 15, 'bold'), fg="white", bg="#1E90FF", width=16, command=lambda: self.thread_it(self.param_print))
self.start_run1.grid(padx=20, pady=0, row=0, column=1)
self.start_run2 = tk.Button(self.runs_button_frame, text='线程测试打印1', font=('行楷', 15, 'bold'), fg="white", bg="#1E90FF", width=16, command=lambda: self.thread_it(self.print1))
self.start_run2.grid(padx=15, pady=0, row=0, column=2)
self.start_run3 = tk.Button(self.runs_button_frame, text='线程测试打印2', font=('行楷', 15, 'bold'), fg="white", bg="#1E90FF", width=16, command=lambda: self.thread_it(self.print2))
self.start_run3.grid(padx=20, pady=0, row=0, column=3)
def thread_it(self, func, *args):
""" 将函数打包进线程 """
self.myThread = threading.Thread(target=func, args=args)
self.myThread .setDaemon(True) # 主线程退出就直接让子线程跟随退出,不论是否运行完成。
self.myThread .start()
def file_input_path(self):
""" 上传文件路径选择 """
path_ = askopenfilename() # 文件选择方法,目录选择是 from tkinter.filedialog import askdirectory,用法一致
self.file_input_dirs = path_ # 将字符串文件地址给变量
self.file_input_entry.delete(0, tk.END) # 将文本输入组件的信息删除
self.file_input_entry.insert(tk.END, path_) # 在文本输入组件,插入文件导入按钮的字符串地址
def param_print(self):
# 如果输入地址和文件选择按钮的值都为None,则提示
if len(self.file_input_entry.get().strip()) < 1 and self.file_input_dirs is None:
messagebox.showwarning(title='小洲助手v1.1警告', message='必须输入或选择文件地址!')
return False
# 如果输入地址为空则选用文件选择按钮的值
if len(self.file_input_entry.get().strip()) > 1:
file_path = self.file_input_entry.get().strip()
else:
file_path = self.file_input_dirs
file_path_content = f"文件地址为:{file_path}"
# 不勾选单选框则值为初始设置的'0', 赋值None
radio_value = 'None' if self.choose_day_value.get() == '0' else self.choose_day_value.get()
radio_value_content = f"单选值为:{radio_value}"
# 不勾选复选框则值为初始设置的0, 赋值None
check_value_one = 'None' if self.choose_number_value_one.get() == 0 else self.choose_number_value_one.get()
check_value_two = 'None' if self.choose_number_value_two.get() == 0 else self.choose_number_value_two.get()
check_value_three = 'None' if self.choose_number_value_three.get() == 0 else self.choose_number_value_three.get()
check_value_content = f'复选值依次为:{check_value_one}, {check_value_two}, {check_value_three}'
self.run_log_print(file_path_content)
self.run_log_print(radio_value_content)
self.run_log_print(check_value_content) # 日志输出
def print1(self):
for i in range(100):
tip_content = f'第{i}次打印 - 我是小洲1'
self.run_log_print(message=tip_content)
time.sleep(0.05) # 睡眠,单位秒
self.run_log_print(message='我是小洲1 - 打印完成')
def print2(self):
for i in range(100, 200):
tip_content = f'第{i}次打印 - 我是小洲2'
self.run_log_print(message=tip_content)
time.sleep(0.05) # 睡眠
self.run_log_print(message='我是小洲2 - 打印完成')
def run_log_print(self, message):
""" 实时更新日志,固定用法 """
self.run_log.config(state=tk.NORMAL)
self.run_log.insert(tk.END, "\n" + message + "\n")
self.run_log.see(tk.END)
self.run_log.update()
self.run_log.config(state=tk.DISABLED)
def clos_window(self):
""" 退出/关闭窗体 固定方法 """
ans = askyesno(title='小洲助手v1.1警告', message='是否确定退出程序?\n是则退出,否则继续!')
if ans:
self.init_window_name.destroy()
sys.exit()
else:
return None
if __name__ == '__main__':
""" 实例化出一个父窗口 """
init_window = tk.Tk()
""" 创建Gui类对象 """
test_gui = TestGui(init_window)
""" 界面循环,实时显示窗体变化 """
init_window.mainloop()
3.运行效果
总结
C语言中文网Tkinter教程(非常详细):http://c.biancheng.net/tkinter/
以上就是今天要讲的内容,本文仅仅介绍了Tk制作Gui界面的简单使用,而Tk为我们提供了大量封装程序功能的函数和方法,丰富用户的体验感,后续有关于tk的常用代码会在这篇博客中持续更新。