使用Tkinter编写一个简单的窗口应用

使用Tkinter编写一个简单的窗口应用

一、前言

​ Tkinter是python中的一个实现可视化窗口的模块,具有使用方便(Python自带、无需下载)、易于上手的优势,足以应付小型应用的开发。
​ 使用Tkinter,就像搭积木一样能将一个个控件(标签、输入框、文本框、按钮等)放置到合适的位置,并赋予它们功能,建立一个简单的窗口应用。
​ 本文章的目的是让小白也能学会使用Python中的Tkinter模块编写一个简单的窗口应用,具有一定的实操性,推荐读者跟着打一下代码。
​ 读完本文章你将学会:使用Frame规划窗口布局,能够大概将Label(标签)、Button(按钮)、Entry(输入框)、Text(文本框)通过pack、grid方法放到所需位置,能够通过按钮实现交互(调用函数),读取输入框中的内容,经过函数处理后在文本框输出,编写一个类似下图的窗口应用,以及如何通过Pyinstaller将py程序打包为exe程序。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nmTmlLpB-1601092903845)(D:\林淼\笔记\Blog\Tkinter实例.png)]
​ 更多相关内容的使用,如Canvas、Menu等,本文章将不会介绍,因为使用以上的内容已经足以搭建一个小型的应用了,以后将会考虑继续更新后面的内容。
​ 另外,本文章使用Python3.8.5版本进行讲解,与老版本的Tkinter模块的使用存在部分差异,推荐读者使用Python3.8.5及以上版本进行学习。

二、控件简介

  • Label: 标签,显示一个文本或图像
  • Entry: 输入框,程序能从中获取输入内容
  • Button: 按钮,通过连接函数来执行一个操作
  • Text: 文本框,可以显示程序输出,支持样式设定
  • Frame: 框架控件,在屏幕上显示一个矩形区域,多用来作为容器

三、实践学习

1. 主窗口的创建以及Label的使用
# 导入Tkinter模块,使用别名tk
import tkinter as tk

# 使用Tk方法创建一个窗口,注意是大写T
window = tk.Tk()
# 给窗口起一个标题
window.title('Tkinter is awesome')
# 设定窗口大小(长x宽,这里是使用字符'x'而不是星号*)
window.geometry('300x500')

# 创建label控件
label = tk.Label(window, text='Hello! Tkinter.', bg='black', fg='white', font=('Consolas', 12), width=30, height=2)
# 这里使用的是键值对(即属性: 值)的方式来设定参数,window表示该标签放置在window上,text为显示文本,bg(background)为背景颜色,fg(fontground)为字体颜色,font=(字体, 字号),width和height表示该标签的宽和高(如height为2表示该标签有2个字符那么高,这与字号的设定相关)

# 将label放置
label.pack()

# 主窗口循环显示
window.mainloop()
# 这一行代码将不断刷新窗口,所有的窗口文件都必须有这一命令,如果没有这一命令窗口将不会显示

测试效果
在这里插入图片描述

2. Button的创建使用
# 导入tkinter模块
import tkinter as tk

clicked = False
def Clicked():
    global clicked
    # 点一次,显示Label显示文本
    if clicked == False:
        clicked = True
        var.set('You have clicked it!')
    # 再点一次,清除Label显示文本
    else:
        clicked = False
        var.set('')

# 创建窗口
window = tk.Tk()
window.title("Let's study Button")
window.geometry('300x200')

# 创建一个Tkinter中的字符串变量
var = tk.StringVar()
# 创建一个标签
label = tk.Label(window, textvariable=var, font=('Consolas', 14), bg='red', fg='black', width=20, height=4)
label.pack()

# 创建button控件
button = tk.Button(window, text='Click it', font=('Consolas', 12), bg='black', fg='white', width=10, height=2, command=Clicked)
button.pack()

window.mainloop()

测试效果
在这里插入图片描述
在这里插入图片描述

3. pack方法和grid方法以及Text和Entry的应用
	通过前面的学习,我们已经知道pack方法是用来放置一个控件的,它具有几个常用的属性如:side、anchor、expand、fill,这里我们重点介绍side和anchor。
	side有四个值:left、right、top和bottom,分别代表左右顶底。anchor是以上下左右(东西南北)来指示位置的,如nw代表左上方(西北方)、n代表上方(北方)。
	详细的可以参照博主快乐清风客写的文章,写得非常详细。https://blog.csdn.net/superfanstoprogram/article/details/83713196

​ 另外一个是我非常推荐使用的grid方法,grid方法具有如下几个常用属性:row、column、padx、pady。
​ row和column是行和列的意思,它会将空间划分为一个二维表格,用行和列表示位置。padx和pady是表示水平间距和垂直间距。
​ 此外还有一个place方法是使用绝对坐标来定位的,这里我们略过,有兴趣可以去搜索一下。
​ 多说无用,看代码吧!

"""
作者:Tuzki
日期:2020-09-26
"""
# 导入tkinter库,并从math库中导入gcd函数
import tkinter as tk
from math import gcd

# 定义一个函数,与按钮链接,求最大公约数
def clicked():
    # 清空text框
    text.delete(1.0, 'end')
    # 使用get方法从输入框中获取数据(默认为字符串),转换为整型
    # 并使用gcd求出最大公约数
    result = gcd(int(entry1.get()), int(entry2.get()))
    # 将最大公约数result插入到文本框text中
    text.insert('insert', result)
    # 此处的'insert'为插入模式,表示在光标处插入
    # 还有一个参数为'end',表示从在结尾插入
    # 此处使用任意一个参数对输出结果都没有影响
# 注:每次调用函数时必须清空文本框,否则将会导致下一次输出时上一次输出结果依然停留

# 创建窗口
window = tk.Tk()
window.title('求最大公约数的简单程序')
window.geometry('300x200')

# 创建标签
label1 = tk.Label(window, text='输入数1', font=('Consolas', 14), width=6, height=2)
label2 = tk.Label(window, text='输入数2', font=('Consolas', 14), width=6, height=2)
# 使用grid放置标签,将标签分别放在第0行第0列和第0行第1列
label1.grid(row=0, column=0)
label2.grid(row=0, column=1)

# 创建输入框,设定宽度为10
entry1 = tk.Entry(window, font=('Consolas', 12), width=10)
entry2 = tk.Entry(window, font=('Consolas', 12), width=10)
# 使用grid放置输入框,将它们分别放在第1行第0列和第1行第1列,并调整水平间距为5
entry1.grid(row=1, column=0, padx=5)
entry2.grid(row=1, column=1, padx=5)

# 创建按钮,使用command属性链接函数clicked(不能带参数)
button = tk.Button(window, text='求最大公约数', font=('Consolas', 14),
                   width=12, height=2, command=clicked)
# 放置按钮,调整水平间距为5,垂直间距为20
button.grid(row=2, column=0, padx=5, pady=20)

# 创建文本框并放置
text = tk.Text(window, font=('Consolas', 12), width=20, height=2)
text.grid(row=2, column=1, padx=5, pady=20)

# 窗口循环
window.mainloop()

测试效果
在这里插入图片描述

4. 使用Frame对窗口进行空间规划
	Frame是一个容器控件,是一个矩形区域,可以承载其他控件,类似于CSS中的div,使用Frame可以更好地规划窗口。
	比如说,像下图求最大公约数,如果使用grid函数来放置按钮,那么,第二个按钮是放在第1行(从0计数)的第2列还是第3列呢?答案是只能放在第二或第三列,那么界面将会变得不协调,于是我们把它划分为多个框,每个框是一个单独的表格,每个表格之间的行列宽高不相互影响,就能很好地解决这一问题。
"""
作者:Tuzki
日期:2020-09-23
"""
"""
作者:Tuzki
日期:2020-09-23
"""
import tkinter as tk
import math

# 求两个数的最大公约数
def Execution2():
    text.delete(1.0, 'end')
    gcd2 = math.gcd(int(entry1.get()), int(entry2.get()))
    text.insert('insert', "{}".format(gcd2))

# 求三个数的最大公约数
def Execution3():
    text.delete(1.0, 'end')
    gcd2 = math.gcd(int(entry1.get()), int(entry2.get()))
    gcd3 = math.gcd(gcd2, int(entry3.get()))
    text.insert('insert', "{}".format(gcd3))

# 求四个数的最大公约数
def Execution4():
    text.delete(1.0, 'end')
    gcd2 = math.gcd(int(entry1.get()), int(entry2.get()))
    gcd3 = math.gcd(gcd2, int(entry3.get()))
    gcd4 = math.gcd(gcd3, int(entry4.get()))
    text.insert('insert', "{}".format(gcd4))

# 创建窗口
window = tk.Tk()
window.title("求最大公约数 by Tuzki")
window.geometry("800x240")

# 创建并使用pack方法进行放置2个Frame
frame_top = tk.Frame(window, width=100, height=2)
frame_bottom = tk.Frame(window, width=100, height=40)
frame_top.pack(side='top')
frame_bottom.pack()

# 在frame_bottom里再放置两个Frame
frame_bottom1 = tk.Frame(frame_bottom, width=100, height=16)
frame_bottom2 = tk.Frame(frame_bottom, width=100, height=16)
frame_bottom1.pack(side='top')
frame_bottom2.pack(side='bottom')

# 创建并放置label,后续不会调用到,因此不使用变量存放,直接设定并放置
tk.Label(frame_top, text='输入数1', width=16, font=('Consolas', 14)).grid(row=0, column=0)
tk.Label(frame_top, text='输入数2', width=16, font=('Consolas', 14)).grid(row=0, column=1)
tk.Label(frame_top, text='输入数4', width=16, font=('Consolas', 14)).grid(row=0, column=2)
tk.Label(frame_top, text='输入数3', width=16, font=('Consolas', 14)).grid(row=0, column=3)
# 若直接返回label().grid/pack,程序将会报错!

# 创建并放置entry,后续会调用到,因此使用变量存放
entry1 = tk.Entry(frame_top, show=None, width=10, font=('Consolas', 14))
entry2 = tk.Entry(frame_top, show=None, width=10, font=('Consolas', 14))
entry3 = tk.Entry(frame_top, show=None, width=10, font=('Consolas', 14))
entry4 = tk.Entry(frame_top, show=None, width=10, font=('Consolas', 14))
entry1.grid(row=1, column=0, padx=30, pady=5)
entry2.grid(row=1, column=1, padx=30, pady=5)
entry3.grid(row=1, column=2, padx=30, pady=5)
entry4.grid(row=1, column=3, padx=30, pady=5)

# 创建并放置三个按钮,为了提高代码可读性分开设定和放置
button1 = tk.Button(frame_bottom1, text='求2个数的最大公约数', font=('Consolas', 14), command=Execution2)
button2 = tk.Button(frame_bottom1, text='求3个数的最大公约数', font=('Consolas', 14), command=Execution3)
button3 = tk.Button(frame_bottom1, text='求4个数的最大公约数', font=('Consolas', 14), command=Execution4)
button1.grid(row=0, column=0, padx=20, pady=20)
button2.grid(row=0, column=1, padx=20, pady=20)
button3.grid(row=0, column=2, padx=20, pady=20)

# 使用pack中的anchor属性,将label放置到frame_top2的左上角
tk.Label(frame_bottom2, text='最大公约数为:', font=('Consolas', 14)).pack(anchor='nw')

# 创建并放置文本框用于输出
text = tk.Text(frame_bottom2, height=2, width=70, font=('Consolas', 14))
text.pack(side='bottom')

# 维持窗口
window.mainloop()

在这里插入图片描述

5. 使用Pyinstaller对程序进行打包
  • 下载安装Pyinstaller:下载Pyinstal有两种方法,一种是通过cmd命令行下载,一种是通过网站下载。
  1. 使用CMD命令行下载:
pip install pyinstaller
  1. 通过网站下载:https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyinstaller
    然后在下载目录下使用cmd命令安装:
pip install "文件名.whl"

以我为例,我是使用pip install "PyInstaller-3.6-py2.py3-none-any.whl"安装的。
安装过程中可能会遇到pip版本太老难以下载安装的问题,推荐逐一使用以下命令进行更新,直到更新成功。

python -m pip install --upgrade pip
python -m pip install -U --force-reinstall pip
pip install --user --upgrade pip
  • 使用Pyinstaller将程序打包
    在源代码(.py)文件所在目录下,使用cmd命令行将程序打包
pyinstaller -w -F 文件名.py

-w和-F是表示去掉控制台窗口并生成单个可执行文件。

各个输入参数的含义:

  • F 表示生成单个可执行文件
  • w 表示去掉控制台窗口,对于GUI图形界面非常有用,但如果你编写的是控制台程序那就忽略这个参数吧
  • p 表示你自己自定义需要加载的类路径,一般情况下用不到
  • i 表示可执行文件的图标

如果对CMD命令行不了解,可以看我的另一篇博文:
https://blog.csdn.net/tuzkizki/article/details/107014794

补充以下代码的self.e()函数:#!/usr/bin/python #coding:utf-8 from tkinter import * import time root = Tk() def cacl(input_str): if "x" in input_str: ret = input_str.split("x") return int(ret[0]) * int(ret[1]) def callback(n): print(n) def callback1(n): print(n) class App: def __init__(self, master): frame1 = Frame(master) frame1.pack() frame = Frame(master) frame.pack() Button(frame, text="1",command=lambda: callback(1) ).grid(row=0,column=0) Button(frame, text="2",command=lambda: callback(2) ).grid(row=0,column=1) Button(frame, text="3",command=lambda: callback(3) ).grid(row=0,column=2) Button(frame, text="4",command=lambda: callback(4) ).grid(row=1,column=0) Button(frame, text="5",command=lambda: callback(5) ).grid(row=1,column=1) Button(frame, text="6",command=lambda: callback(6) ).grid(row=1,column=2) Button(frame, text="7",command=lambda: callback(7) ).grid(row=2,column=0) Button(frame, text="8",command=lambda: callback(8) ).grid(row=2,column=1) Button(frame, text="9",command=lambda: callback(9) ).grid(row=2,column=2) Button(frame, text="0",command=lambda: callback(0) ).grid(row=3,column=0) Button(frame, text="+",command=lambda: callback1("+") ).grid(row=3,column=1) Button(frame, text="-",command=lambda: callback1("-") ).grid(row=3,column=2) Button(frame, text="*",command=lambda: callback1("*") ).grid(row=4,column=1) Button(frame, text="/",command=lambda: callback1("/") ).grid(row=4,column=2) Button(frame, text="=", command=self.say_hi).grid(row=4,column=0) w = Label(frame1,text="输入结果") w.pack() self.e = Entry(frame1) self.e.pack(padx=5) w1 = Label(frame1,text="计算结果") w1.pack() v = StringVar() e1 = Entry(frame1, textvariable=v) v.set("") self.v = v e1.pack() def say_hi(self): print("hi there, everyone!",self.e.get()) input_str = self.e.get() self.v.set(cacl(input_str)) app = App(root) root.mainloop()
06-11
您可以尝试将如下代码添加到App类中: ```python def say_hi(self): print("hi there, everyone!",self.e.get()) input_str = self.e.get() self.v.set(cacl(input_str)) ``` 这是一个名为`say_hi`的方法,它将从输入框中获取文本,将其传递给`cacl`方法进行计算,并将计算结果设置为计算结果文本框的值。 在这个方法中,`self.e.get()`将获取输入框中的文本。然后,它将调用`cacl`方法进行计算,并将计算结果设置为计算结果文本框的值。 最后,你需要将`=`按钮的命令设置为`self.say_hi`,这样当用户单击该按钮时,将调用`say_hi`方法进行计算并更新计算结果文本框的值。在App类的构造函数中,将以下代码添加到按钮的创建行: ```python Button(frame, text="=", command=self.say_hi).grid(row=4,column=0) ``` 完整的代码如下所示: ```python from tkinter import * import time root = Tk() def cacl(input_str): if "x" in input_str: ret = input_str.split("x") return int(ret[0]) * int(ret[1]) def callback(n): print(n) def callback1(n): print(n) class App: def __init__(self, master): frame1 = Frame(master) frame1.pack() frame = Frame(master) frame.pack() Button(frame, text="1",command=lambda: callback(1) ).grid(row=0,column=0) Button(frame, text="2",command=lambda: callback(2) ).grid(row=0,column=1) Button(frame, text="3",command=lambda: callback(3) ).grid(row=0,column=2) Button(frame, text="4",command=lambda: callback(4) ).grid(row=1,column=0) Button(frame, text="5",command=lambda: callback(5) ).grid(row=1,column=1) Button(frame, text="6",command=lambda: callback(6) ).grid(row=1,column=2) Button(frame, text="7",command=lambda: callback(7) ).grid(row=2,column=0) Button(frame, text="8",command=lambda: callback(8) ).grid(row=2,column=1) Button(frame, text="9",command=lambda: callback(9) ).grid(row=2,column=2) Button(frame, text="0",command=lambda: callback(0) ).grid(row=3,column=0) Button(frame, text="+",command=lambda: callback1("+") ).grid(row=3,column=1) Button(frame, text="-",command=lambda: callback1("-") ).grid(row=3,column=2) Button(frame, text="*",command=lambda: callback1("*") ).grid(row=4,column=1) Button(frame, text="/",command=lambda: callback1("/") ).grid(row=4,column=2) Button(frame, text="=", command=self.say_hi).grid(row=4,column=0) w = Label(frame1,text="输入结果") w.pack() self.e = Entry(frame1) self.e.pack(padx=5) w1 = Label(frame1,text="计算结果") w1.pack() v = StringVar() e1 = Entry(frame1, textvariable=v) v.set("") self.v = v e1.pack() def say_hi(self): print("hi there, everyone!",self.e.get()) input_str = self.e.get() self.v.set(cacl(input_str)) app = App(root) root.mainloop() ``` 注意,这个计算器只能计算形如"n x m"的表达式,如果你想要计算其他形式的表达式,需要对`cacl`方法进行修改。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值