使用Python Tkinter制作简单的程序界面

上一篇写到利用Python写了一个对文本进行读取和修改的小工具,最近两天在研究给这个小程序加个界面,对于GUI这里不做赘述,到现在也算是初步完成了,写个博客记录记录。

首先是界面工具的选用,在菜鸟教程上看到的GUI模块有3款,原文链接Python GUI编程(Tkinter) 文中只对Tkinter工具做了简单的介绍,并没有太深的讲解;查找之下找到了简书上的Tkinter教程,原文链接(八)Python 图形化界面设计 这个文档对Tkinter模块做了详细的介绍和示例,有这方面需要的朋友可以详细的阅读练手。值得一提的是,文本框的输入使能在文中并没有介绍到,我在另一篇文章中找到了有关文本框输入使能的介绍,原文链接Tkinter中关于如何让用户无法编辑Text,又可进行插入、删除操作 此外,为了实现按钮结束程序的功能,需要销毁root的root对象,简书上的Tkinter教程有用到这个对象,但没有过多的描述,为了找到这个对象在vscode里尝试输入root.cl和root.des后,发现root自带一个destroy对象,确定是销毁root的对象。

由于是第一次做界面,所以定的要求比较低,并不追求界面的美观,只需要基本的功能实现即可。首先遇到的是功能按钮化,原本整合在一个while里的主程序需要拆分成若干个子程序,原程序和拆分后的程序如下:

此时的代码是基于上代加了输入验证和时间模块引入,并做了一些输出上的微调

while True:
    print("**************************你爱用不用的报销记录工具**************************\n")
    choose = input("选择你要进行的操作:\n1.提交报销\n2.结束报销\n3.查看所有记录\n4.结束程序\n输入:")#功能选择
    print()
    if not choose :
        print("要我帮你做选择?")
        continue
    elif str(choose).isdigit() == False :
        print("脸滚键盘呢?")
        continue
    fb = open("%s报销记录.txt"%(ADDR),mode = 'a')#确保文件存在,若不存在则在指定目录新建一个
    fb.close()
    if int(choose) == 1:
        fb = open("%s报销记录.txt"%(ADDR),mode = 'r')#打开记录文本
        getline = 0 #获取当前行数,即最后一个编号
        for line in fb.readlines():
            getline += 1
        fb.close()
        while True:
            date = input("输入提交日期,如:20190101,不填则默认当前日期\n输入:")#获取日期,金额和时长
            if not date:
                date = DATE
            elif int(date) > int(DATE):
                print("日期输入有误!提交日期不可晚于今天!重新输入!")
                continue
            money = int(input("输入报销金额\n输入:"))
            days = int(input("输入出差时长\n输入:"))
            break
        line = openfile()
        addline(line,getline,date,money,days)
        print("添加成功!\n")
        
    elif int(choose) == 2:
        fb = open("%s报销记录.txt"%(ADDR),mode = 'r')#打开记录文本
        getline = 0 #获取当前行数,即最后一个编号
        for line in fb.readlines():
            getline += 1
        fb.close()
        line = openfile()
        while True:
            num = int(input("输入要结束的编号\n输入:"))
            if num > getline:
                print("无此记录!确认后再输入!\n")
                continue
            if line[num].find('Y') != -1 :
                print("这条记录已经完成报销了,你别是在逗我吧")
                continue
            date = input("输入提交日期,如:20190101,不填则默认当前日期\n输入:")#获取日期和金额
            if not date:
                date = DATE
            elif int(date) >= int(DATE):
                print("日期输入有误!提交日期不可晚于今天!重新输入!")
                continue
            money = int(input("输入报销金额\n输入:"))
            break
        endline(line,num,date,money)
        print("添加成功!\n")
    elif int(choose) == 3:
        line = openfile()
        if line == []:
            print("文件为空!\n")
        for i in line:
            print(i)
    elif int(choose) == 4:
        break
    else :
        print("没那么多功能!")

拆分后的代码:
原本的输入和输出有了明显的变化,输入是获取输入框的内容,输出是将输出内容添加到文本框中

def choose1():
    txt.config(state = NORMAL)#文本框使能开,允许输入内容
    #输入验证
    flag = True#使while只运行一次,while的意义在于输入有误时能使用break阻止后续代码的运行
    while flag:
        money = inp3.get()
        #money = int(input("输入报销金额\n输入:"))
        days = inp1.get()
        #days = int(input("输入出差时长\n输入:"))
        if (not money) or (not days):
            txt.insert(END,"输入不完整!\n")
            txt.config(state = DISABLED)#在程序中断时及时关闭文本框使能,保证文本框只能被程序修改
            break
        date = inp2.get()
        #date = input("输入提交日期,如:20190101,不填则默认当前日期\n输入:")#获取日期,金额和时长
        if not date:
            date = DATE
        elif int(date) > int(DATE):
            txt.insert(END,("日期输入有误!提交日期不可晚于今天!重新输入!\n"))
            txt.config(state = DISABLED)
            break
            #print("日期输入有误!提交日期不可晚于今天!重新输入!")
        fb = open("报销记录.txt",mode = 'r')#打开记录文本
        getline = 0 #获取当前行数,即最后一个编号
        for line in fb.readlines():
            getline += 1
        fb.close()

        line = openfile()
        addline(line,getline,date,money,days)
        txt.insert(END,"添加成功!\n")
        txt.insert(END,'\n')
        txt.config(state = DISABLED)#本次功能结束,关闭文本框使能

        inp1.delete(0, END)  # 清空输入
        inp2.delete(0, END)  # 清空输入
        inp3.delete(0, END)  # 清空输入
        #print("添加成功!\n")
        flag = False

def choose2():
    txt.config(state = NORMAL)
    flag = True
    while flag:
        #输入检查
        fb = open("报销记录.txt",mode = 'r')#打开记录文本
        getline = 0 #获取当前行数,即最后一个编号
        for line in fb.readlines():
            getline += 1
        fb.close()
        num = inp1.get()
        if not num:
            txt.insert(END,"选择的编号不能为空!\n")
            txt.config(state = DISABLED)
            break
            #num = int(input("输入要结束的编号\n输入:"))
        elif str(num).isdigit() == False :
            txt.insert(END,"让你输编号呢!\n")
            #print("让你输编号呢!\n")
            txt.config(state = DISABLED)
            break
        num = int(num)
        if num > getline:
            txt.insert(END,"无此记录!确认后再输入!\n")
            #print("无此记录!确认后再输入!\n")
            txt.config(state = DISABLED)
            break
            #flag = False
        elif line[num].find('Y') != -1:
            txt.insert(END,"这条记录已经完成报销了,你别是在逗我吧!\n")
            #print("这条记录已经完成报销了,你别是在逗我吧")
            txt.config(state = DISABLED)
            break
            #flag = False
        date = inp2.get()
        #date = input("输入提交日期,如:20190101,不填则默认当前日期\n输入:")#获取日期和金额
        if not date:
            date = DATE
        elif int(date) >= int(DATE):
            txt.insert(END,"日期输入有误!提交日期不可晚于今天!重新输入!\n")
            #print("日期输入有误!提交日期不可晚于今天!重新输入!")
            txt.config(state = DISABLED)
            break
            #flag = False
        
        money = inp3.get()
        line = openfile()
        #money = int(input("输入报销金额\n输入:"))
        endline(line,num,date,money)
        txt.insert(END,"添加成功!\n")
        txt.insert(END,'\n')
        txt.config(state = DISABLED)
        #print("添加成功!\n")
        inp1.delete(0, END)  # 清空输入
        inp2.delete(0, END)  # 清空输入
        inp3.delete(0, END)  # 清空输入
        flag = False

def choose3():
    txt.config(state = NORMAL)
    line = openfile()
    if line == []:
        txt.insert(END,"文件为空!\n")
        #print("文件为空!\n")
    else:
        for i in line:
            txt.insert(END,i)
            #print(i)
    txt.insert(END,'\n')
    txt.config(state = DISABLED)

def choose4():
    root.destroy()
    #break

界面化之后,相较于shell里执行,界面化的输出不会自动换行,需要在Text.insert里加入额外的换行
界面模块:

from tkinter import  *
import datetime

time = datetime.datetime.now()
DATE = str(time.year) + str(time.month) + str(time.day)#限定日期,取当前日期,确保输入日期不在未来
#ADDR = "D:工程部svn\"

#确保文件存在
fb = open("报销记录.txt",mode = 'a')
fb.close()

root = Tk()
root.title("Py报销记录工具")
root.geometry('480x480')

lb0 = Label(root, text='爱用不用的报销记录工具',bg='#d3fbfb',fg='red',font=('华文新魏',24),width=20,height=2,relief=SUNKEN)
lb0.place(relx=0.1, rely=0.0, relwidth=0.8, relheight=0.1)

lb1 = Label(root, text="时长/编号:")
lb1.place(relx=0.0, rely=0.1, relwidth=0.15, relheight=0.1)

inp1 = Entry(root)
inp1.place(relx=0.15, rely=0.11, relwidth=0.15, relheight=0.08)

lb2 = Label(root, text="日期:")
lb2.place(relx=0.35, rely=0.1, relwidth=0.1, relheight=0.1)

inp2 = Entry(root)
inp2.place(relx=0.45, rely=0.11, relwidth=0.2, relheight=0.08)

lb3 = Label(root, text="金额:")
lb3.place(relx=0.7, rely=0.1, relwidth=0.1, relheight=0.1)

inp3 = Entry(root)
inp3.place(relx=0.8, rely=0.11, relwidth=0.2, relheight=0.08)

btn1 = Button(root, text='添加记录', command=choose1)
btn1.place(relx=0.1, rely=0.2, relwidth=0.3, relheight=0.1)

btn2 = Button(root, text='结束记录', command=choose2)
btn2.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1)

btn3 = Button(root, text='查看记录', command=choose3)
btn3.place(relx=0.6, rely=0.2, relwidth=0.3, relheight=0.1)

btn4 = Button(root, text='结束程序', command=choose4)
btn4.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1)

txt = Text(root)
txt.place(rely=0.6, relheight=0.4)
txt.config(state = DISABLED)#文本框初始使能关

root.mainloop()

界面效果:


界面化后原来的模块代码:

def openfile():
    txt.insert(END,"开始读取文件\n")
    #print("开始读取文件")
    fb = open("报销记录.txt",mode = 'r')
    lines = []
    for line in fb:
        lines.append(line)
    txt.insert(END,"读取完成\n")
    #print("读取完成")
    fb.close()
    return lines

def addline(line,getline,date,money,days):
    #txt.insert(END,("添加前:",line,'\n'))
    #print("添加前:",line)
    line.append("%d N %s %d %d "%(int(getline),date,int(money),int(days)))
    #txt.insert(END,("添加后:",line,'\n'))
    #print("添加后:",line)
    fb = open("报销记录.txt",mode = 'w')
    for i in range(len(line)):
        s = str(line[i]).replace('[','').replace(']','').replace("'",'').replace(',','').replace('\n','')#去除[],去除单引号
        #txt.insert(END,(s,'\n'))
        #print(s)
        fb.write(s)
        fb.write('\n')
    txt.insert(END,"添加程序运行完成!\n")
    #print("添加程序运行完成!")
    fb.close()

def endline(line,num,date,money):
    #print(line[num])
    line[num] = line[num].replace('N','Y')
    #print(line[num])
    addstr = str(date) + ' ' + str(money)
    line[num] += addstr
    #print(line)
    fb = open("报销记录.txt",mode = 'w')
    for i in range(len(line)):
        s = str(line[i]).replace('[','').replace(']','').replace("'",'').replace(',','').replace('\n','')#去除[],去除单引号
        #txt.insert(END,(s,'\n'))
        #print(s)
        fb.write(s)
        fb.write('\n')
    txt.insert(END,"结束程序运行完成!\n")
    #print("结束程序运行完成!")
    fb.close()

基本功能已经做好了,后续准备引入父容器,使界面更美观;再引入用户和数据库吧。
望大佬们多多批评指正,菜鸟在此拜谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值