前言
上机实践课程开始了,嗯,老师来了之后念了下PPT,然后说:开始做吧.........
然后就开始了Python的GUI之路,以前没接触过PYthon的可视化界面(虽然这样很不明智)
但是现在做起来感觉写小工具还挺方便的,当时搜到的第一个库便是Tkinter就直接开始写了
后来发现QT很不错的样子,下个实验就用QT吧.然后关于Tkinter(python3.6)
计算器源码 ennn.....有的命名不规范.......
首先对于python中栈的实现是通过list的方式模拟
pop()出栈,append()入栈
首先我们来看一下常用的TKinter提供的核心小构件类:
小构件类 | 描述 |
---|---|
Button | 按钮 |
Canvas | 结构化图形,用于绘制图形,创建图形编辑器以及实现自定义小构件类 |
Checkbutton | 单击复选按钮在值之间切换 |
Entry | 文本域或称文本框 |
Frame | 容器(可包含其他的小构件) |
Label | 显示文本或图像 |
Menu | 显示下拉菜单和弹出菜单的菜单栏 |
Menubutton | 下拉菜单的菜单按钮 |
Message | 类似于标签显示文本,但能自动将文本放在给定宽高内 |
Radiobutton | 单选按钮 |
Text | 格式化的文本显示,支持内嵌图片和文本,允许用不同风格和属性显示和编辑文本 |
开始一个窗口
做一个可视化的东西,首先想到的坑定是窗口吧
窗口又有很多构成,比如title,ico,size,bd,菜单等.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import tkinter
import os
from tkinter import *
class Calculator( object ):
"""计算器"""
def __init__( self ):
self .tk = tkinter.Tk() #实例化
self .tk.title( '计算器' )
self .tk.minsize( 370 , 460 )
self .tk.maxsize( 400 , 400 )
#也可以用self.tk.resizable(0, 0)来禁止调节大小
self .tk.iconbitmap(os.getcwd() + '/favicon.ico' )
def start( self ):
self .tk.mainloop()
if __name__ = = '__main__' :
NewCalculator = Calculator()
NewCalculator.start()
|
这里就生成了一个基本的窗口,对于其中的mainloop()
的作用
如果我们删除它,窗口会一闪而过,它就是为了防止这种情况
面板显示
做成计算器之后坑定要先是计算结果,这里就需要生成显示面板
当然我们也会很自然地联想到显示内容的字体设置等需求,具体事例在下面代码
1
2
3
4
5
6
7
8
9
10
11
12
|
....
import tkinter.font as tkfont
....
#字体设置
self .EntryFont = tkfont.Font( self .tk,size = 13 )
self .ButtonFont = tkfont.Font( self .tk,size = 12 )
#面板显示
self .count = tkinter.StringVar()
self .count. set ( '0' )
self .label = tkinter.Label( self .tk,bg = '#EEE9E9' ,bd = '3' ,fg = 'black' ,anchor = 'center' ,font = self .EntryFont,textvariable = self .count)
self .label.place(y = 10 ,width = 380 ,height = 40 )
....
|
其中tkinter中面板Lable有一些参数,这里用到的基本上也可以满足常见的需求了
其中bg是背景色,fg是前景色,改变内容的颜色,anchor是定位内容在面板中的位置,如下图
方向 | 示例 | 表格 |
---|---|---|
nw | n | ne |
w | center | e |
sw | s | se |
关于面板以及后边的Button的定位,可以用很多方式,place可以准确的定位,也可以用pack(),grid()
对于计算器place是更好的,能够准确定位每一个控件
其中字体也可以直接在Lable()
加参数,例如font=("Arial,6")
textvariable相当于“监听”的作用,绑定tkinter中的string,就可以用set()
的方式方便的改变面板的内容
按钮,输入框设置
按钮,输入框的参数和面板里面的是相似的
1
2
3
4
5
|
self .NumButton = tkinter.Button(master = self .tk,relief = GROOVE,bg = '#EE6A50' ,text = self .ButtonList[ 0 ],
font = self .ButtonFont,command = self .clear)
self .NumButton.place(x = 30 ,y = 80 ,width = 70 ,height = 55 )
self .shiEntry = Entry( self .baoxianTk,validate = 'key' ,validatecommand = ( self .checkNum, '%P' ),font = self .EntryFont)
self .shiEntry.place(x = 190 ,y = 80 )
|
一样的是通过bg等参数设置基础的样式,只不过这里会通过command绑定事件,类似于JQ中的.click
这里的place也是为了能够准确定位才使用的,其中的relief代表着Button的样式
relief=FLAT or GROOVE or RAISED or RIDGE or SOLID or SUNKEN
其中删除输入框的输入内容
1
2
3
|
text.delete( 10 ) #删除索引值为10的值
text.delete( 10 , 20 ) #删除索引值从10到20之前的值
text.insert( 0 , END) #删除所有值
|
输入限制
在设计功能的时候我们可能需要用户输入数字等,这里可以进行限制一下
Button参数中validate指定什么时候执行validatecommand绑定的函数,使用%P可以实时获取输入的内容
当validate选项指定为key的时候,有任何的输入操作都会被拦截,这个时候返回True白能量才会输入到Entry
1
2
3
4
5
6
7
8
9
|
self .checkNum = self .baoxianTk.register( self .validateNum)
self .gerenEntry = Entry( self .baoxianTk,validate = 'key' ,validatecommand = ( self .checkNum, '%P' ),font = self .EntryFont)
self .gerenEntry.place(x = 190 ,y = 190 )
#验证是否输入数字
def validateNum( self ,content):
if content.isdigit() and int (content)> = 0 or content = = "":
return True
else :
return False
|
validateNum()
函数可以根据自己的需求进行更改
启用验证validate选项可以设置的值有:
名称 | 事件 |
---|---|
focus | 当 Entry 组件获得或失去焦点的时候验证 |
focusin | 当 Entry 组件获得焦点的时候验证 |
focusout | 当 Entry 组件失去焦点的时候验证 |
key | 当输入框被编辑的时候验证 |
all | 当出现上边任何一种情况的时候验证 |
拓展符号设计
这个小计算器中我增加了%,/,sqrt三个符号
对于他们的实现我的思路是添加到面板之前检测一下传入的button内容
如果是这三种符号则做出对应的处理
其中需要注意如果是多位数或者带有符号式子
不能直接进行变换,需要判断你要转置的数字的位数,我的具体方式如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
def checkList( self ):
result = 0
locate = - 1
listSum = 0
for length in range ( 0 , len ( self .inputlist)):
if re.findall(r '[-+*/]' , str ( self .inputlist[length])):
result = 1
if length>locate:
locate = length
else :
pass
if result = = 1 :
for i in range (locate + 1 , len ( self .inputlist)):
listSum + = int ( self .inputlist[i]) * ( 10 * * ( len ( self .inputlist) - i - 1 ))
else :
for j in range ( 0 , len ( self .inputlist)):
listSum + = int ( self .inputlist[j]) * ( 10 * * ( len ( self .inputlist) - j - 1 ))
return listSum,locate
#添加button
def addButton( self ,button):
if button = = self .ButtonList[ 18 ]:
listSum,locate = self .checkList()
if locate = = - 1 :
self .inputlist = [ str ( round ( eval ( '1/' + str (listSum)), 5 ))]
else :
for k in range (locate + 1 , len ( self .inputlist)):
del self .inputlist[k]
self .inputlist.append( str ( round ( eval ( '1/' + str (listSum)), 5 )))
elif button = = self .ButtonList[ 19 ]:
pass
elif button = = self .ButtonList[ 20 ]:
pass
else :
self .inputlist.append(button)
self .count. set ( self .inputlist)
|
关于lambda
百度百科:Lambda表达式是Python中一类特殊的定义函数的形式,使用它可以定义一个匿名函数
与其它语言不同,Python的Lambda表达式的函数体只能有唯一的一条语句,也就是返回值表达式语句
搜索更多文章后理解更多,Lambda函数可以说是对按钮起到“call back”的作用
如果我们不使用Lambda进行中间函数的延迟回调,在创建按钮的同时command绑定的函数会被调用
即如下面两句代码的区别,第二句在进行创建时会直接执行knobDown函数
1
2
|
self .NumButton = tkinter.Button(master = self .tk,relief = GROOVE,bg = '#BFEFFF' ,text = self .ButtonList[ 20 ], font = self .ButtonFont,command = lambda : self .knobDown( self .ButtonList[ 20 ]))
self .NumButton = tkinter.Button(master = self .tk,relief = GROOVE,bg = '#BFEFFF' ,text = self .ButtonList[ 20 ], font = self .ButtonFont,command = self .knobDown( self .ButtonList[ 20 ]))
|
更详细的解释可以参考文末最后两个文章,还是前辈写得好
关于单选框
本来想实现PPT中给出的示例-房贷计算的拓展,但是一直这个单选框产生BUG就放弃了
下面的示例是从网上摘抄过来的,具体的网址忘了
就是通过variable绑定一个IntVar()
,通过.get()
方式可以获取Radiobutton中value的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#!/usr/bin/env python
import tkinter
from tkinter import *
import tkinter.font as tkfont
root = tkinter.Tk()
val = tkinter.IntVar()
val. set ( 0 )
def func1():
if val.get() = = 0 :
label.configure(text = 'radio 0' )
else :
label.configure(text = 'radio 1' )
label = tkinter.Label(root, text = 'radio 0' )
label.pack()
r0 = tkinter.Radiobutton(text = 'radio0' , variable = val, value = 0 )
r0.pack()
r1 = tkinter.Radiobutton(text = 'radio1' , variable = val, value = 1 )
r1.pack()
b = tkinter.Button(root, text = 'button' , command = func1)
b.pack()
root.mainloop()
|
打包
1
2
3
4
|
C:\Users\bayi\Desktop\shiyan\progrem
(venv) λ pip install pyinstaller
C:\Users\bayi\Desktop\shiyan\progrem
(venv) λ pyinstaller - F - w - i favicon.ico run.py
|
一开始因为代码中的设置ico图标为下面代码第一行
windows下打包路径识别有问题,把图标换到一个路径短的地方
修改成绝对路径就OK了(下面代码第二行,exe和ico要放在同一个目录下
1
2
|
self .baoxianTk.icobitmap( 'favicon.ico' )
self .baoxianTk.iconbitmap(os.getcwd() + '/favicon.ico' )
|
效果预览
虽然是现学现卖和对于别人的老知识,但是成功之后还是挺有成就感的(and我似乎对美工要求挑剔........
调颜色和样式能挑半天,包括以前的那个爬虫的前端
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:https://segmentfault.com/a/1190000012474725