让你的打字快如闪电!用Python做打字软件,附超详解和源码链接

如果您觉得此项目有一些不完美的地方,可以在评论区评论,也可以在Github的仓库中发布issue,个人建议issue

Github地址:https://github.com/Github-Programer/PyProject-DZgame

⚡打字通⚡

  • 项目结果
  • 详细解释
    • 基本结构+标题标签+提示+样例+输入框
      • 随机生成字符串
      • Label使用+cursors参数
      • Entry输入框
      • Frame中的并列三个按钮
    • 弹出结果+重置按钮+隐藏和重现控件方法
      • 计时
        • 开始计时:pushStart()
        • 结束计时:pushEnd()
      • 重置所有+隐藏控件
      • 检查正确
      • 按钮绑定回车
    • Copyright © 制作
    • grid和pack
      • grid和pack无法放在一起
      • grid怎么用?
  • In The Future()
  • 源码

  • 贡献⭐
    • 联系方式

版本正在更新……,目前1.3.2

项目结果

GIF制作十分粗劣,自己看着都揪心,不过基本看清楚了

详细解释

下面我会详细解释一下,如果不看,就不看吧,直接向下看源码,传送门

基本结构+标题标签+提示+样例+输入框

让你的打字快如闪电!用Python做打字软件,附超详解和源码链接_第1张图片

随机生成字符串

我制作了一个函数,叫getRandom_str(),可以每次调用获取随机字符串

这里用到了ascll码的字符和ascll编号转换的用法——ord()和chr()

资料:

  • 菜鸟教程ord:https://www.runoob.com/python3/python3-func-ord.html
  • 菜鸟教程chr:https://www.runoob.com/python3/python3-func-chr-html.html
def getRandom_str():
    characters = []  # 0~26
    for i in range(0, 50):
        tmp = random.randint(0, 25)
        characters.append(chr(ord('a') + tmp)) #智能生成从a+0到a+25的字符

    # print(characters)
    chstr = ""
    for i in characters:
        chstr += i
    return chstr

Label使用+cursors参数

这个无法截图,就是你把鼠标放在标题位置(黄色),会变成一个别的样子

在这里插入图片描述

lb = Label(root, bitmap="hourglass",
           compound="left",
           cursor="target",  #重要的就是这个cursor
           text="霹雳⚡-打字通⌨",
           fg="blue", bg="yellow",
           anchor=CENTER, font=("Helvetic", 20, "bold")
           )

cursor参数的值常用的有这几个:
资料:https://blog.csdn.net/cool99781/article/details/106193125

Entry输入框

INframe = Frame(root, width=70)  # 定义输入框架
intxtL = Label(INframe, text="输入> ")

intxt = Entry(INframe, width=50, show="*")

光有一个输入框是不行的,需要一个提示:‘输入>’,把这个存在label里面,再建立一个输入框,show='*'是输入时显示为星号,用一个框架frame放在一起,最后grid就行

让你的打字快如闪电!用Python做打字软件,附超详解和源码链接_第2张图片

Frame中的并列三个按钮

需要一个Frame将三个按钮并列放在一起,所以这个比较简单

btnframe = Frame(root, width=60)
# BUTTON 按钮    开始和结束
btnStart = Button(btnframe, text="开始输入", fg="blue", width=20,
                  command=pushStart)
btnEnd = Button(btnframe, text="输入结束", fg="blue", width=20,
                command=pushEnd)
btnExit = Button(btnframe, text='退出程序', fg="red", width=20,
                 command=root.destroy)

每一个按钮都有一个command参数,意思是点击后执行什么,第一个就是pushStart()函数,启动计时器,清除结果;第二个是pushEnd()函数,功能比较多——计算用时,显示重新开始按钮,清空很多数据;第三个并没有执行函数,而是root.destroy(),这个方法可以让程序直接关闭。

弹出结果+重置按钮+隐藏和重现控件方法

计时

开始计时:pushStart()

使用datetime模块的datetime类中的utcnow(),存在一个str里,记录初始时间

这是按钮调用的函数

def pushStart():
    # timestrS=time.time()
    global timestrS
    timestrS = datetime.utcnow()
    print("get timestamp start of->timestrS={0}".format(timestrS))
    # rebtn.grid_forget()

结束计时:pushEnd()

首先把copy_的隐藏掉,最后显示,getStr是获取输入,global可以将变量全局化,我想谁打字都不会超过一个小时吧,所以把当前时间和初始时间相减得出时间,然后计算对了几个、错了几个、正确率,下面会讲到check函数。然后将结果显示在一个标签中,并加上一个按钮重新开始,按钮的操作是reinfo(),就是重置,下面也会讲到的。

def pushEnd():
    copy_.grid_forget()
    getStr(intxt)
    global cyongshi
    #fmmf = time.time()
    fmmf = datetime.utcnow()
    #timtmp = fmmf - timestrS
    timtmps = timestrS.second+timestrS.minute*60
    timtmpe = fmmf.second+fmmf.minute*60
    #print("get timestamp this of->time.time()={0}".format(time.time()))
    #print("get timestamp minx of->timtmp={0}".format(timtmp))
    timestrLast = timtmpe - timtmps
    print("get timestamp end of->timestrLast={0}".format(timestrLast))
    print("时间:{0}".format(timestrLast))
    cyongshi = timestrLast

    ccList = check(chstr, constin)
    endstr = '生成->' + chstr + '\n' + '输入->' + constin + '\n'
    endstr += "时间:" + str(cyongshi) + '秒' + '\n'
    endstr += '正确率:' + str(ccList[0]) + '%\n'
    endstr += '对了:' + str(ccList[1]) + '个\n'
    endstr += '错了:' + str(ccList[2]) + '个\n'
    # PHOTO IMAGE
    lbot.configure(width=60, text=endstr,
                   # bitmap='',
                   compound='left',
                   anchor=SW,
                   bg='skyblue',
                   justify='left')
    rebtn.configure(text='重新开始?', bg='#EA5529',
                    fg='#FFCCCC', command=reinfo, font=('microsoft YAHEI', 13, 'normal'))
    # out
    lbot.grid()
    rebtn.grid()
    copy_.grid(row=7, column=0)

重置所有+隐藏控件

reinfo不长,首先将输入框中的值全部删掉,然后还记得lbot和rebtn是什么?就是重置按钮和谈出结果,.grid_forget()就是隐藏的意思,将两个控件隐藏,pack和place两种布局也有pack.forget()和place.forget(),最后重置样例,重新获取随机字符串

def reinfo():
    global chstr
    intxt.delete(0, END)
    # lbot.config(text='')
    lbot.grid_forget()
    rebtn.grid_forget()
    timestrS = None
    timestrLast = None
    chstr = getRandom_str()
    lbtip.configure(text="样例" + chstr)

检查正确

就是check函数,调用原本的字符串和你输入的字符串,注意:for循环用两个变量遍历两个字符串、字典、元组、列表都要用zip函数,下面就有。统计正确率和错误率,然后返回一个列表,这是Python的特性。

def check(index: str, commit: str) -> list:
    # 首先需要一个记录原来字符串长度
    aclen = 0.0
    celen = 0.0
    zql = 0.0  # 正确率
    # 循环遍历
    for i, j in zip(index, commit):
        if i == j:
            aclen += 1.0
            print('aclen++, aclen={0}'.format(aclen))
        else:
            celen += 1.0
            print('celen++, celen={0}'.format(celen))
    zql = float(aclen / 50) * 100.0
    print('zql={0}'.format(zql))

    ainfo = [zql, aclen, celen]
    return ainfo

按钮绑定回车

xxx.bind("", def)即可绑定enter键,不过这里的def函数必须要加self,而点击命令中无需加self

因此可以在创建一个函数之后,另外再创建一个调用函数的函数加self即可

但是如果你绑定了回车,按钮就不可用了,所以你就建立一个间接函数,如下所示(不是程序中的)

def test():
    pass
 
def test_fun(self):
    test()
 
text1 = Entry(input_word)
# pack是加载到窗口
text1.pack(side='left') 
'''
两个函数的意义是既能enter运行,又可以点击运行,方便操作,扩大使用
bind绑定enter键
注意里面是return 而不是enter
'''
b = Button(station_frame,text='开始',command=test)
b.pack(side='left')
text1.bind("", test_fun)

Copyright © 制作

就是一个标签,使用了grid的网格放在了居中位置,等重置弹出之后改变位置始终保持最下面

copy_ = Label(root, text='Copyright(C)2020/5 by Thomas\nE-mail:[email protected]',
              bg='lavender')

本来说再弄个框架的,但是看没必要了,就算了
在这里插入图片描述

grid和pack

grid和pack无法放在一起

详见:https://blog.csdn.net/cool99781/article/details/106200985
如果一个程序中有grid和pack同时存在,那么就会报错

_tkinter.TclError: cannot use geometry manager pack inside . which already has slaves managed by grid

原因:

一个程序中,只能使用一种布局,否则会报上面的错误。

几何方法 描述
pack() 包装
grid() 网格
place() 位置

把pack都改成grid就可以

grid怎么用?

英文解释:grid——网格

这是一种网格布局,和pack不同

其中重要的两个参数是:row、column,row是行,column是列,比如
让你的打字快如闪电!用Python做打字软件,附超详解和源码链接_第3张图片
这是一个温度转换的程序,一个控件占了一行一列,所以计算按钮在row=3, column=3的位置,这个程序的代码:

from tkinter import *

def calculate():
    fValue = float(entry.get())
    cValue = (fValue - 32)* 5/ 9
    lb1['text']= str(cValue)

root = Tk()
root.title("温度转换")

entry = Entry(root)
entry.grid(column=2, row=1)

lb1= Label(root)
lb1.grid(column=2, row=2)

btn= Button(root, text="计算", command=calculate)
btn.grid(column=3, row=3)

lb2= Label(root, text="°F")
lb2.grid(column=3, row=1)

lb3= Label(root, text="等于摄氏")
lb3.grid(column=1, row=2)

lb4= Label(root, text="°C")
lb4.grid(column=3, row=2)

root.mainloop()

In The Future()

未来版本——2.0:废除随机字符串机制,转为文档(比如一个英文小说),文档可以从网上搜索保存到本地

未来版本——4.0:网络排名,目标时间xxx年

源码

仓库:https://github.com/Github-Programer/PyProject-DZgame

快点star


还需要一个ico,csdn上传不了

# coding: UTF-8
#!/usr/bin/python3

from tkinter import *
import random
import time
from datetime import datetime
import os


def getRandom_str():
    characters = []  # 0~26
    for i in range(0, 50):
        tmp = random.randint(0, 25)
        characters.append(chr(ord('a') + tmp))

    # print(characters)
    chstr = ""
    for i in characters:
        chstr += i
    return chstr

# ---------------------------check---------------------------

# 查看


def check(index: str, commit: str) -> list:
    # 首先需要一个记录原来字符串长度
    aclen = 0.0
    celen = 0.0
    zql = 0.0  # 正确率
    # 循环遍历
    for i, j in zip(index, commit):
        if i == j:
            aclen += 1.0
            print('aclen++, aclen={0}'.format(aclen))
        else:
            celen += 1.0
            print('celen++, celen={0}'.format(celen))
    zql = float(aclen / 50) * 100.0
    print('zql={0}'.format(zql))

    ainfo = [zql, aclen, celen]
    return ainfo
# ---------------------------check---------------------------


constin = None  # 输入汇总changliang
cyongshi = None  # 用时
timestrS = datetime.utcnow()  # 时间记录器-first
timestrLast = 0  # 时间记录器-last
chstr = None

ft = r"E:\ProgramThomas\Coding-Notes\Project\PYT\打字游戏Python的GUI界面\resource\loggerstr.log"
'''
def msgShow():
    label["text"] = 'I Love Python'
    label["bg"] = 'orangerad'
'''


def getStr(ent):
    global constin
    # 返回Entry的值
    tmp = ent.get()
    print("输入:{0}".format(tmp))
    constin = tmp


def pushStart():
    # timestrS=time.time()
    global timestrS
    timestrS = datetime.utcnow()
    print("get timestamp start of->timestrS={0}".format(timestrS))
    # rebtn.grid_forget()


def reinfo():
    global chstr
    intxt.delete(0, END)
    # lbot.config(text='')
    lbot.grid_forget()
    rebtn.grid_forget()
    timestrS = None
    timestrLast = None
    chstr = getRandom_str()
    lbtip.configure(text="样例" + chstr)


    # lbtip.grid()
'''
def itg(chstr, constin):
    #"时间:"+str(cyongshi)+'秒'
    ccList = check(chstr, constin)
    endstr = "时间:" + str(cyongshi) + '秒' + '\n'
    endstr += '正确率:' + str(ccList[0]) + '\n'
    endstr += '对了:' + str(ccList[1]) + '个\n'
    endstr += '错了:' + str(ccList[2]) + '个\n'
    return endstr
'''


def pushEnd():
    copy_.grid_forget()
    getStr(intxt)
    global cyongshi
    #fmmf = time.time()
    fmmf = datetime.utcnow()
    #timtmp = fmmf - timestrS
    timtmps = timestrS.second+timestrS.minute*60
    timtmpe = fmmf.second+fmmf.minute*60
    #print("get timestamp this of->time.time()={0}".format(time.time()))
    #print("get timestamp minx of->timtmp={0}".format(timtmp))
    timestrLast = timtmpe - timtmps
    print("get timestamp end of->timestrLast={0}".format(timestrLast))
    print("时间:{0}".format(timestrLast))
    cyongshi = timestrLast

    ccList = check(chstr, constin)
    endstr = '生成->' + chstr + '\n' + '输入->' + constin + '\n'
    endstr += "时间:" + str(cyongshi) + '秒' + '\n'
    endstr += '正确率:' + str(ccList[0]) + '%\n'
    endstr += '对了:' + str(ccList[1]) + '个\n'
    endstr += '错了:' + str(ccList[2]) + '个\n'
    # PHOTO IMAGE
    lbot.configure(width=60, text=endstr,
                   # bitmap='',
                   compound='left',
                   anchor=SW,
                   bg='skyblue',
                   justify='left')
    rebtn.configure(text='重新开始?', bg='#EA5529',
                    fg='#FFCCCC', command=reinfo, font=('microsoft YAHEI', 13, 'normal'))
    # out
    lbot.grid()
    rebtn.grid()
    copy_.grid(row=7, column=0)


def pushEND_FUN(self):
    pushEnd()


# --------------------------------
root = Tk()
#root.state('zoomed')
root.title("打字游戏1.3.1")
root.iconbitmap("iconbitmap.ico")
#root.geometry("500x400")  # 779*655
lb = Label(root, bitmap="hourglass",
           compound="left",
           cursor="target",
           text="霹雳⚡-打字通⌨",
           fg="blue", bg="yellow",
           anchor=CENTER, font=("Helvetic", 20, "bold")
           )
# r"E:\ProgramThomas\Coding-Notes\Project\PYT\打字游戏Python的GUI界面\resource\BITMAP_TITLE.ico"
lb2 = Label(root, bitmap="question",
            compound="left",
            text="提示:打字游戏,点击 开始 按钮即开始计时,最后点击 提交 按钮即可",
            fg="#FF0000", bg="lightyellow",
            )
#copy_F = Frame(root)
copy_ = Label(root, text='Copyright(C)2020/5 by Thomas\nE-mail:[email protected]',
              bg='lavender')
# beiy: -> : , padx=20, pady=10

# 生成随机字符串已经转移到函数
chstr = getRandom_str()

print(chstr)
lbtip = Label(root, bitmap="info",
              compound="left",
              text="样例" + chstr,
              fg="green", bg="#cccccc",
              font=("simsun", 12), underline=True)
# Entry cursor circle

INframe = Frame(root, width=70)  # 定义输入框架
intxtL = Label(INframe, text="输入> ")

intxt = Entry(INframe, width=50, show="*")

btnframe = Frame(root, width=60)
# BUTTON 按钮    开始和结束
btnStart = Button(btnframe, text="开始输入", fg="blue", width=20,
                  command=pushStart)
btnEnd = Button(btnframe, text="输入结束", fg="blue", width=20,
                command=pushEnd)
btnExit = Button(btnframe, text='退出程序', fg="red", width=20,
                 command=root.destroy)

lbot = Label(root)
rebtn = Button(root)

# cc = Cac(chstr, constin)   class init to cc var


lb.grid()
lb2.grid()
lbtip.grid()
INframe.grid()
intxtL.grid(row=3, column=0, sticky=W)  # 输入>Label
intxt.grid(row=3, column=1)  # 输入框Entry th
btnframe.grid()


btnStart.grid(row=4, column=0)
btnEnd.grid(row=4, column=1)
btnExit.grid(row=4, column=2)
#root.bind('', pushEnd)

copy_.grid(row=5, column=0)

root.bind('', pushEND_FUN)


# lbot.grid()

# textTip = Text(root)
# textTip.pack(fill=BOTH, expand=True, padx=3, pady=2)
# textTip.insert(END, chstr)
root.mainloop()
print("时间={0}".format(cyongshi))

贡献⭐

您觉得怎么样?觉得对您有帮助或者很有趣可以star一下并推广一下

如果有需要更改可以fork一下

如果有疑问或者功能不足或者有结构错误可以提出issue,这里的评论不全面

联系方式

如果发给我邮箱或者QQ,请先在博客评论区提醒我

你可能感兴趣的:(#,Python图形化界面编程,字符串,列表,python,tkinter,gui)