千纬认字(更新增加部首及笔顺动画)程序源码及win版发布

这次更新变化还是比较大的,一是增加听写功能,从1至25按顺序给小朋友按,听写好就按下是否听写正确。二是提醒功能,如果超过30秒、60秒、90秒不按(即不做题)就用声音提醒小朋友做题。三是采集2700多个小学生生字的部首,在无声出题时帮助小朋友选择字,这里还有个更新就是出题是会连续三个界面的字相同,但出题的顺序不同,无声出题是第一次是拼音加2组词,第二次是拼音加部首加一组词,第三次是部首加2组词。

一、采集www.cidianso.com网站的部首及笔画动画gif源代码:

# -*- coding: utf-8 -*-
"""
Created on Sun May 19 15:19:17 2024

@author: YBK
"""
import urllib
import sqlite3
from urllib.request import urlopen,Request
import urllib,string
from bs4 import BeautifulSoup as bf
from time import time, sleep
import random

db_filepath = 'D:\\bee\\qwrz2\\src\\qwrz2\\resources\\qwrznew.db'
conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
c = conn.cursor()
i = 0
while i < 2272:
    cursor = c.execute("SELECT id,hz FROM hz WHERE bh is Null limit 0,1;")
    row = cursor.fetchone()
    hzid = row[0]
    strzi = row[1]
    url = f"https://www.cidianso.com/{strzi}_zi/"
    url = urllib.parse.quote(url, safe=string.printable)
    html = urlopen(url)
    # 获取的html内容是字节,将其转化为字符串
    html_text = bytes.decode(html.read())
    
    obj = bf(html_text,'html.parser')
    index_hotlist = obj.find_all('div',class_='small_nanex new_li')
    for div in index_hotlist:
        divxx = div.find_all('img')
        for p in divxx:
            if p.get('src'):
                zisrc = p.get('src')
    index_hotlist = obj.find_all('div',class_='name')
    py = []
    for div in index_hotlist:
        if strzi + '的部首' in div.get_text():
            bs = div.get_text().replace(strzi + '的部首','').strip(' ') 
        if strzi + '的拼音' in div.get_text():
            ahrf = div.find_all('a')
            for ahr in ahrf:
                py.append(ahr.get_text())
            #py = div.get_text().replace(strzi + '的拼音','').strip('\n').strip(' ').strip('')
        if strzi + '的笔画' in div.get_text():
            bh = div.get_text().replace(strzi + '的笔画','').strip(' ')     
        if strzi + '的笔顺' in div.get_text():
            bshun = div.get_text().replace(strzi + '的笔顺','').strip(' ') 
    py1 = ''
    py1 = str.join(",", py)
    image_url='https://www.cidianso.com'+zisrc
    urllib.request.urlretrieve(image_url,'E:\\7777\\zigif\\'+str(hzid)+'.gif')#网址、存储路径
    
    print(strzi,py1,bs,bh,bshun)
    if len(bshun)>0:
        c.execute("UPDATE hz SET bs = ?,pys = ?,bh = ?,bshun = ? WHERE id = ?;", (bs,py1,bh,bshun,hzid))
        conn.commit()
    i = i + 1
    sleep(random.randint(1,2))
c.close()
conn.close()

二、主程序源代码:

from functools import partial
import toga
from toga.style.pack import COLUMN, LEFT, RIGHT, ROW, Pack
#from toga.fonts import Font
import sqlite3
import random
from time import time, sleep
from pathlib import Path
import miniaudio
import datetime
import threading
from threading import Timer
import shutil
#导入必要的库,其中这个miniaudio库是可以在Android上运行的,我尝试了很多播放声音的库,只有这个能被Beeware编译到安卓程序上

resources_folder = Path(__file__).joinpath("../resources/").resolve()
resources_folder1 = Path(__file__).joinpath("../resources/sy1").resolve()
resources_folder2 = Path(__file__).joinpath("../resources/sy2").resolve()
resources_folder3 = Path(__file__).joinpath("../resources/sy3").resolve()
giffolder = Path(__file__).joinpath("../resources/gif").resolve()
#Font.register('simkai',str(resources_folder.joinpath("simkai.ttf")))
#注册楷体simkai,这个在电脑上能用但手机上就不行了
#方便测试我这里写了个变量sjcs,1为手机,0为电脑,2为boox平板
db_filepath = resources_folder.joinpath("qwrznew.db")
sjcs = 0
if sjcs == 1:
    sj_file = '/data/data/com.qwrz.qwrz2/qwrz.db'
    if Path(sj_file).exists():
        db_filepath = sj_file
    else:
        shutil.copy(db_filepath, sj_file)
        db_filepath = sj_file
elif sjcs == 2:
    db_filepath = '/storage/emulated/0/Pictures/qwrznew.db'
#使用手机将数据库存放在手机的/data/data/文件夹中,不用获取权限,减少麻烦,我以前的版本是放在文档中方便分析数据
conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
c = conn.cursor()
cursor = c.execute("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='tx'")
row = cursor.fetchone()
have_tx = row[0]
if have_tx ==0:
    c.execute('''CREATE TABLE tx (
    tid   INTEGER PRIMARY KEY AUTOINCREMENT,
    nj    INTEGER,
    hid   INTEGER REFERENCES hz (id),
    cid   INTEGER REFERENCES record (cid),
    times INTEGER DEFAULT (0) 
    );
    ''')
    conn.commit()
#创建听写表,用于记录听写信息
cursor = c.execute("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='setupme'")
row = cursor.fetchone()
have_set = row[0]
if have_set ==0:
    c.execute('''CREATE TABLE setupme (
    have_record2 INTEGER,
    have_jfen    INTEGER,
    set_gz       INTEGER,
    g16_fs       INTEGER,
    g16_width    INTEGER,
    g16_height   INTEGER,
    g25_fs       INTEGER,
    g25_width    INTEGER,
    g25_height   INTEGER,
    app_name     TEXT);
    ''')
    conn.commit()
    c.execute("INSERT INTO setupme(app_name,g25_height,g25_width,g25_fs,g16_height,g16_width,g16_fs,set_gz,have_jfen,have_record2) VALUES ('千纬认字(听写版)',68,68,22,85,85,25,16,0,0);")
    conn.commit()
    cursor = c.execute("SELECT app_name,g25_height,g25_width,g25_fs,g16_height,g16_width,g16_fs,set_gz,have_jfen,have_record2 FROM setupme")
    row = cursor.fetchone()
    globals()['app_name'] = row[0]
    globals()['g25_height'] = row[1]
    globals()['g25_width'] = row[2]
    globals()['g25_fs'] = row[3]
    globals()['g16_height'] = row[4]
    globals()['g16_width'] = row[5]
    globals()['g16_fs'] = row[6]
    globals()['set_gz'] = row[7]
    globals()['have_jfen'] = row[8]
    globals()['have_record2'] = row[9]
else:
    cursor = c.execute("SELECT app_name,g25_height,g25_width,g25_fs,g16_height,g16_width,g16_fs,set_gz,have_jfen,have_record2 FROM setupme")
    row = cursor.fetchone()
    globals()['app_name'] = row[0]
    globals()['g25_height'] = row[1]
    globals()['g25_width'] = row[2]
    globals()['g25_fs'] = row[3]
    globals()['g16_height'] = row[4]
    globals()['g16_width'] = row[5]
    globals()['g16_fs'] = row[6]
    globals()['set_gz'] = row[7]
    globals()['have_jfen'] = row[8]
    globals()['have_record2'] = row[9]
#创建setupme表,用于记录app的有关参数,这个是以前做网站的经验,这样有利于让app多功能
if globals()['have_record2'] == 0:
    cursor = c.execute("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='record2'")
    row = cursor.fetchone()
    have_record2a = row[0]
    if have_record2a == 0:
        c.execute('''
        CREATE TABLE record2 (
            rid INTEGER PRIMARY KEY AUTOINCREMENT,
            hid INTEGER REFERENCES hz (id),
            cid INTEGER REFERENCES record (cid),
            yt  INTEGER);
        ''')
        conn.commit()
        c.execute("update setupme set have_record2 = 1")
        conn.commit()
    else:
        c.execute("update setupme set have_record2 = 1")
        conn.commit()  
#是否存在record2表,没有就建表,并在参数表设置为1,该表用于记录答题时长
if globals()['have_jfen'] == 0:
    cursor = c.execute("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='jfen'")
    row = cursor.fetchone()
    have_jfena = row[0]
    if have_jfena == 0:
        c.execute('''CREATE TABLE jfen (
        jid INTEGER PRIMARY KEY AUTOINCREMENT,
        rq  TEXT,
        jf  INTEGER);
        ''')
        conn.commit()
        c.execute("update setupme set have_jfen = 1")
        conn.commit()
    else:
        c.execute("update setupme set have_jfen = 1")
        conn.commit()
#是否存在jfen表,没有就建表,并在参数表设置为1,下次就不要判断是否有这个表
current_date = datetime.datetime.now()
formatted_date = current_date.strftime("%Y-%m-%d")
cursor = c.execute("SELECT count(*) FROM jfen WHERE rq='"+ formatted_date +"'")
row = cursor.fetchone()
if row[0] == 0:
    query_sql = "INSERT INTO jfen (rq,jf) VALUES (?,?);"
    c.execute(query_sql, (formatted_date,0,))
    conn.commit()
c.close()
conn.close()
#在积分表中写入今天的一行,用于记录今天的积分
global duihz, duipy, duizc1, duizc2, duizc3,duizc4,duizc5, duid, kw, jj
global stime, etime, ytime, begintime, testcs, cuo_cs, yshen, cid, tjcs
names = globals()
cid = 0
yshen = 0
rongy = 0 #实际是用于听写,不是容易
testtime = 0 #用于记录测试次数,每16-25个字测试3次
testcs = 0
cuo_cs = 0
stime = time()
begintime = time()
rid = 0
cuot = 0
duid = 0
jf = 0
kn = 0
jj = ''
zjf = 0
global njt,njt1
njt = '一年级'
#上面是全局参数和默认值
def bfsy(hzid,idsc):
    if hzid < 1001:
        stream = miniaudio.stream_file(str(resources_folder1.joinpath(str(hzid) + '.wav')))
    elif hzid > 1000 and hzid < 2001:
        stream = miniaudio.stream_file(str(resources_folder2.joinpath(str(hzid) + '.wav')))
    elif hzid > 2000 and hzid < 3001:
        stream = miniaudio.stream_file(str(resources_folder3.joinpath(str(hzid) + '.wav')))
    elif hzid > 3000 and hzid < 4001:
        stream = miniaudio.stream_file(str(resources_folder3.joinpath('cuo.wav')))
        #大于3000为错,其余为对
    elif hzid > 4000 and hzid < 5001:
        stream = miniaudio.stream_file(str(resources_folder3.joinpath('dui.wav')))
    elif hzid > 5000 and hzid < 6001:
        #提醒来做题
        stream = miniaudio.stream_file(str(resources_folder3.joinpath('zt.wav')))
    elif hzid > 6000 and hzid < 7001:
        stream = miniaudio.stream_file(str(resources_folder3.joinpath('zt1.wav')))
    elif hzid > 7000 and hzid < 8001:
        stream = miniaudio.stream_file(str(resources_folder3.joinpath('zt2.wav'))) 
    with miniaudio.PlaybackDevice() as device:
        device.start(stream)
        sleep(idsc)
def bfsya(hzid,idsc):
    if hzid < 1001:
        stream = miniaudio.stream_file(str(resources_folder1.joinpath(str(hzid) + 'a.wav')))
    elif hzid > 1000 and hzid < 2001:
        stream = miniaudio.stream_file(str(resources_folder2.joinpath(str(hzid) + 'a.wav')))
    elif hzid > 2000 and hzid < 3001:
        stream = miniaudio.stream_file(str(resources_folder3.joinpath(str(hzid) + 'a.wav')))
    with miniaudio.PlaybackDevice() as device:
        device.start(stream)
        sleep(idsc)
#播放声音函数,bfsya是用于播放带a的wav文件
def maxmin(xzng):
    if xzng < 9:
        yshen = 0
    else:
        yshen = 1
    if xzng > 16:
        globals()['rongy'] = 1
    else:
        globals()['rongy'] = 0
    if xzng in (1,9,17):
        njt = '一年级'
        njt1 = '二年级上'
    elif xzng in (2,10,18):
        njt = '二年级'
        njt1 = '三年级上'
    elif xzng in (3,11,19):
        njt = '三年级'
        njt1 = '四年级上'
    elif xzng in (4,12,20):
        njt = '四年级'
        njt1 = '五年级上'
    elif xzng in (5,13,21):
        njt = '五年级'
        njt1 = '六年级上'
    elif xzng in (6,14,22):
        njt = '六年级'
        njt1 = '五年级'
    else:
        njt = '二年级'
        njt1 = '三年级'
    conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
    c = conn.cursor()
    if xzng == 15:
        query_sql = "update setupme set set_gz = 16"
        c.execute(query_sql)
        conn.commit()
    if xzng == 16:
        query_sql = "update setupme set set_gz = 25"
        c.execute(query_sql)
        conn.commit()
    #16格和25格的设置,写入setupme参数表用于下次打开        
    c.close()
    conn.close()
    return(njt,njt1,yshen)

njt,njt1,yshen = maxmin(3)
#选择年级和有声无声的函数,默认是3
def u_record(testcs,cuo_cs,yshen,cid):
    #mt修改为记录是否有声的开关
    if testcs > 0:
        conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
        c = conn.cursor()
        c.execute("UPDATE record SET ts = ?,ct = ?,mt = ? WHERE cid = ?;", (testcs,cuo_cs,yshen,cid))
        conn.commit()
        c.close()
        conn.close()
#记录每次的题数,错题数,每题用多少秒,每个界面用一个cid  
def u_cs1(duid):
    conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
    c = conn.cursor()  
    query_sql = "update hz set cs1 = cs1 + 1 where id= ?"
    c.execute(query_sql, (str(duid),))
    conn.commit()
    c.close()
    conn.close()
def u_jfen(jf):
    conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
    c = conn.cursor()
    current_date = datetime.datetime.now()
    formatted_date = current_date.strftime("%Y-%m-%d")
    cursor = c.execute("SELECT count(*) FROM jfen WHERE rq='"+ formatted_date +"'")
    row = cursor.fetchone()
    if row[0] ==0:
        query_sql = "INSERT INTO jfen (rq,jf) VALUES (?,?);"
        c.execute(query_sql, (formatted_date,0,))
        conn.commit()
        query_sql = "update jfen set jf = jf + ? where rq= ?"
        c.execute(query_sql, (jf,formatted_date,))
        conn.commit()
    else:
        query_sql = "update jfen set jf = jf + ? where rq= ?"
        c.execute(query_sql, (jf,formatted_date,))
        conn.commit()
    c.close()
    conn.close()
#记录这个汉字的练习次数+1
def u_cs(addcs,duid):
    conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
    c = conn.cursor()
    query_sql = "update hz set cs = cs + ? where id= ?"
    c.execute(query_sql, (str(addcs),str(duid),))
    conn.commit()
    c.close()
    conn.close()
#为某个汉字加积分
def j_cs(addcs,duid):
    conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
    c = conn.cursor()
    query_sql = "update hz set cs = cs - ? where id= ?"
    c.execute(query_sql, (str(addcs),str(duid),))
    conn.commit()
    c.close()
    conn.close()
#为某个汉字减少积分
def tj_cs():
    if globals()['testcs'] == 0:
        conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
        c = conn.cursor()
        query_str = 'select rq,sum(ts),sum(ct) from record group by rq order by rq desc limit 0,4;'
        cursor = c.execute(query_str)
        rows = cursor.fetchall()
        stext3 = ""
        for row in rows:
            #采用去重统计点错用时较长的题
            #cursor = c.execute("SELECT avg(yt) FROM record2 where cid in (select cid from record where rq ='"+ row[0] +"') and yt < 45000;")
            cursor = c.execute("SELECT avg(yt),count(yt) FROM (SELECT *,rank() over (PARTITION by (hid*10000+cid) order by yt desc) as rank FROM record2 where cid in (select cid from record where rq ='"+ row[0] +"' and mt = 0) and yt < 30000 ) where rank =1;")
            row1 = cursor.fetchone()
            mt = row1[0]
            if mt == None:
                mt = 0
            yzyt = row1[1]
            cursor = c.execute("SELECT avg(yt) FROM (SELECT *,rank() over (PARTITION by (hid*10000+cid) order by yt desc) as rank FROM record2 where cid in (select cid from record where rq ='"+ row[0] +"' and mt > 0) and yt < 30000 ) where rank =1;")
            row1 = cursor.fetchone()
            ymt = row1[0]
            if ymt == None:
                ymt = 0
            cursor = c.execute("SELECT sum(yt) FROM record2 where cid in (select cid from record where rq ='"+ row[0] +"') and yt < 45000")
            row1 = cursor.fetchone()
            zyt = row1[0]
            if zyt == None:
                zyt = 0
            else:
                zyt = int(zyt /1000 /60)
            stext3 += "%s:做%d(%d)题,%d错,%d分钟,每题%d(%d)毫秒\n" % (row[0],row[1],yzyt,row[2],zyt,mt,ymt)
        c.close()
        conn.close()
        globals()['tjcs'] = stext3
    else:
        stext3 = globals()['tjcs']
    return(stext3)
#在界面的下面显示最近4天学习总题数等信息,方便家长检查孩子的学习情况
def in_record2(hid,cid,ytime):
    conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
    c = conn.cursor()
    query_str = 'INSERT INTO record2 (hid,cid,yt) VALUES (?,?,?);'
    c.execute(query_str,(hid,cid,ytime,))
    conn.commit()
    c.close()
    conn.close()
    
def get_numbers(numbers):
    alen = random.randint(2,int(len(numbers)/4))
    index = random.randint(0, len(numbers) - alen)
    return numbers[index:index+alen]
def remove_element(items, remove_items):
    for item in remove_items:
        if item in items:
            items.remove(item)
    return items
def randshu():
    return random.randint(1,9)/10
def randii(setgz):
    ii1 = list(range(1,(setgz + 1)))
    iig = get_numbers(ii1)
    ii1 = remove_element(ii1, iig)
    ri = random.randint(0,9)
    if ri < 4:
        random.shuffle(ii1)
    else:
        random.shuffle(ii1,randshu)
    index = random.randint(0,len(ii1))
    iic = ii1[:index]
    iic.extend(iig)
    iiout = iic + ii1[index:]
    return iiout
#上面4个函数用于生成一个随机列表,里面有一段是连续的
def addfh(original_list):
    x = 0
    while x < len(original_list):
        if '!' not in original_list[x]:
            original_list[x] = original_list[x] + '!' + str(x)
        x = x + 1
    return original_list

def delfh(original_list):
    x = 0
    while x < len(original_list):
        original_list[x] = original_list[x].split('!')[0]
        x = x + 1
    return original_list
#上面2个函数,为列表的各个元素中空值的加上符号和删除符号,保证排序不会变动
def set_all(njt,njt1):
    globals()['testtime'] = globals()['testtime'] + 1
    if globals()['rongy'] == 1:
        globals()['testtime'] = 1 #听写模式时,永远重新出题
    if globals()['testtime'] > 3:
        globals()['testtime'] = 1 #3次后变为1,重新出题
    if globals()['testtime'] > 1 and globals()['testtime'] <= 3:
        oii = globals()['ii']
        #print(globals()['hz'])
        orderii = randii(globals()['set_gz'])
        orderi = [x - 1 for x in orderii]
        xi = []
        i = 0
        while i < len(orderii):
            xi.append(orderii.index(oii[i])+1)
            i = i + 1
        ii = xi
        hz = []
        py = []
        zc1 = []
        zc2 = []
        zc3 = []
        zc4 = []
        zc5 = []
        hzid = []
        kw = []
        bs = []
        idsc = []
        hzid = sorted(globals()['hzid'], key=lambda x: orderi.index(globals()['hzid'].index(x)))
        hz = delfh(sorted(addfh(globals()['hz']), key=lambda x: orderi.index(addfh(globals()['hz']).index(x))))
        #print(hz)
        py = delfh(sorted(addfh(globals()['py']), key=lambda x: orderi.index(addfh(globals()['py']).index(x))))
        zc1 = delfh(sorted(addfh(globals()['zc1']), key=lambda x: orderi.index(addfh(globals()['zc1']).index(x))))
        zc2 = delfh(sorted(addfh(globals()['zc2']), key=lambda x: orderi.index(addfh(globals()['zc2']).index(x))))
        zc3 = delfh(sorted(addfh(globals()['zc3']), key=lambda x: orderi.index(addfh(globals()['zc3']).index(x))))
        zc4 = delfh(sorted(addfh(globals()['zc4']), key=lambda x: orderi.index(addfh(globals()['zc4']).index(x))))
        zc5 = delfh(sorted(addfh(globals()['zc5']), key=lambda x: orderi.index(addfh(globals()['zc5']).index(x))))
        kw = delfh(sorted(addfh(globals()['kw']), key=lambda x: orderi.index(addfh(globals()['kw']).index(x))))
        bs = delfh(sorted(addfh(globals()['bs']), key=lambda x: orderi.index(addfh(globals()['bs']).index(x))))
        idsc = sorted(globals()['idsc'], key=lambda x: orderi.index(globals()['idsc'].index(x)))
        
        globals()['ii'],globals()['hzid'],globals()['hz'],globals()['py'],globals()['zc1'],globals()['zc2'] = [],[],[],[],[],[]
        globals()['zc3'],globals()['zc4'],globals()['zc5'],globals()['kw'],globals()['bs'],globals()['idsc'] = [],[],[],[],[],[]
    else:
        conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
        c = conn.cursor()
        cursor = c.execute("SELECT round(avg(cs)) from hz where nj like '%" + njt + "%' or nj like '%" + njt1 + "%';")
        row = cursor.fetchone()
        csavg = row[0]
        randomi = random.randint(0, 2)
        if njt == '一年级':
            nj = 1
        elif njt == '二年级':
            nj = 2
        elif njt == '三年级':
            nj = 3
        elif njt == '四年级':
            nj = 4
        elif njt == '五年级':
            nj = 5
        else:
            nj = 6
        
        if globals()['rongy'] == 1:
            cursor1 = c.execute("select count(*) from hz where nj like '%" + njt + "%' or nj like '%" + njt1 + "%'")
            row1 = cursor1.fetchone()
            njcount = row1[0]
            cursor1 = c.execute('select count(*) from tx where nj = ?;',(nj,))
            row1 = cursor1.fetchone()
            txcount = row1[0]
            if txcount == 0:
                maxtimes = 1
            else:
                cursor1 = c.execute('select max(times) from tx where nj = ?;',(nj,))
                row1 = cursor1.fetchone()
                maxtimes = row1[0]
            cursor1 = c.execute('select count(*) from tx where nj = ? and times = ?;',(nj,maxtimes,))
            row1 = cursor1.fetchone()
            nowtxcount = row1[0]
            #nowtxcount为本轮听写的所有的字
            if njcount - nowtxcount < 25:
                maxtimes = maxtimes + 1
            #上面为确定maxtimes
            cursor = c.execute("SELECT id, hz, py, zc1, zc2, zc3, zc4, zc5, kw, bs, sc from hz where (nj like '%" + njt + "%' or nj like '%" + njt1 + "%') and id not in (select hid from tx where nj = " + str(nj) + " and times = " + str(maxtimes) + ") ORDER BY RANDOM() LIMIT " + str(globals()['set_gz']))
            rows = cursor.fetchall()
            for row in rows:
                c.execute('insert into tx (nj,hid,cid,times) values (?,?,?,?);',(nj,row[0],globals()['cid'],maxtimes,))
                conn.commit()
        #三种难度,1是按积分最小的练习,2是按积分在平均值以内的练习,3是随机练习
        else:
            if randomi == 0:
                globals()['kn'] = 3
                cursor = c.execute("SELECT id, hz, py, zc1, zc2, zc3, zc4, zc5, kw, bs, sc from hz where nj like '%" + njt + "%' or nj like '%" + njt1 + "%' order by cs asc limit 0," + str(globals()['set_gz']))
                rows = cursor.fetchall()
            elif randomi == 1:
                globals()['kn'] = 2
                cursor = c.execute("SELECT id, hz, py, zc1, zc2, zc3, zc4, zc5, kw, bs, sc from hz where (nj like '%" + njt + "%' or nj like '%" + njt1 + "%') and cs <= " + str(csavg) + " ORDER BY RANDOM() LIMIT " + str(globals()['set_gz']))
                rows = cursor.fetchall()
            else:
                globals()['kn'] = 1
                cursor = c.execute("SELECT id, hz, py, zc1, zc2, zc3, zc4, zc5, kw, bs, sc from hz where nj like '%" + njt + "%' or nj like '%" + njt1 + "%' ORDER BY RANDOM() LIMIT " + str(globals()['set_gz']))
                rows = cursor.fetchall()
        hz = []
        py = []
        zc1 = []
        zc2 = []
        zc3 = []
        zc4 = []
        zc5 = []
        hzid = []
        kw = []
        bs = []
        idsc = []
        i = 1
        for row in rows:
            if i < (globals()['set_gz'] + 1):
                hzid.append(row[0])
                hz.append(row[1])
                py.append(row[2])
                zc1.append(str(row[3]))
                zc2.append(str(row[4]))
                zc3.append(str(row[5]))
                zc4.append(str(row[6]))
                zc5.append(str(row[7]))
                kw.append(row[8])
                bs.append(row[9])
                idsc.append(row[10])
            i = i + 1
        #只有听写时,列表按顺序排列
        if globals()['rongy'] == 1:
            ii = list(range(1,(globals()['set_gz'] + 1)))
        else:
            ii = randii(globals()['set_gz'])
        c.close()
        conn.close()
    return ii,hzid,hz,py,zc1,zc2,zc3,zc4,zc5,kw,bs,idsc
#按年级返回16/25个汉字的拼音组词、课文、id、答题次数和音频文件的播放长度

def is_integer(s):
    try:
        int(s)
        return True
    except ValueError:
        return False

def hello():
    #msg="现在时间是:"+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+",第一次提醒你"
    #print(msg)
    play_sound_background(5500,3.432)    
def hello1():
    play_sound_background(6500,3.623) 
    #msg="现在时间是:"+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+",第二次提醒你"
    #print(msg)
def hello2():
    play_sound_background(7500,4.113) 
    #msg="现在时间是:"+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+",第三次提醒你"
    #print(msg)    
   
globals()['ttt'] = 0

names['t_' + str(globals()['ttt'])] = Timer(30, hello)
names['t_' + str(globals()['ttt'])].setDaemon(True) 
names['t_' + str(globals()['ttt'])].start()
names['t1_' + str(globals()['ttt'])] = Timer(60, hello1)
names['t1_' + str(globals()['ttt'])].setDaemon(True) 
names['t1_' + str(globals()['ttt'])].start()
names['t2_' + str(globals()['ttt'])] = Timer(90, hello2)
names['t2_' + str(globals()['ttt'])].setDaemon(True) 
names['t2_' + str(globals()['ttt'])].start()
def build(app):
    # 定义组件
    c_box = toga.Box()
    b1_box = toga.Box()
    b2_box = toga.Box()
    b3_box = toga.Box()
    b4_box = toga.Box()
    if globals()['set_gz'] == 25:
        b5_box = toga.Box()
    box = toga.Box()
    abox = toga.Box()
    bigbox = toga.Box()
    image = toga.Image(str(giffolder.joinpath(str(random.randint(1, 2791))+'.gif')))
    imageview = toga.ImageView(image=image,style=Pack(width=100, height=100, padding=8))
    c_input = toga.TextInput(readonly=True,style=Pack(font_size=22))
    c_label = toga.Label("请选择几年级,(有声),还可以选择16或25格为下次模式", style=Pack(text_align=LEFT))
    c_label1 = toga.Label("", style=Pack(text_align=LEFT, font_size=12))
    c_label2 = toga.Label("", style=Pack(text_align=LEFT))
    c_label3 = toga.Label("", style=Pack(text_align=LEFT))
    
    
    

        
    #界面设置
    def bt1(bb, widget):
        #msg="现在时间是:"+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+",做题时间!"
        #print(msg)
        names['t_' + str(globals()['ttt'])].cancel()
        names['t1_' + str(globals()['ttt'])].cancel()
        names['t2_' + str(globals()['ttt'])].cancel()
        globals()['ttt'] = globals()['ttt'] + 1
        if globals()['ttt'] >= 60:
            globals()['ttt'] = 0
        names['t_' + str(globals()['ttt'])] = Timer(30, hello)
        names['t_' + str(globals()['ttt'])].setDaemon(True)
        names['t_' + str(globals()['ttt'])].start()
        names['t1_' + str(globals()['ttt'])] = Timer(60, hello1)
        names['t1_' + str(globals()['ttt'])].setDaemon(True)
        names['t1_' + str(globals()['ttt'])].start()
        names['t2_' + str(globals()['ttt'])] = Timer(90, hello2)
        names['t2_' + str(globals()['ttt'])].setDaemon(True)
        names['t2_' + str(globals()['ttt'])].start()
        if is_integer(bb):
            xzng = int(bb)
        else:
            xzng = bb
        globals()['testcs'] += 1
        globals()['etime'] = time()
        globals()['ytime'] = int(etime - stime)
        yytime = int((etime - stime)*1000)
        if duid > 0 and cid > 0 and rid > 0 and globals()['rongy'] != 1:
            in_record2(duid,cid,yytime)
        #记录用时
        if rid == 0:
            current_date = datetime.datetime.now()
            formatted_date = current_date.strftime("%Y-%m-%d")
            formatted_time = current_date.strftime("%H:%M:%S")
            #每次rid=0时,生成一个记录,记录学习情况
            conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
            c = conn.cursor()
            c.execute("INSERT INTO record (rq,sj,ts,ct,mt) VALUES (?,?,?,?,?);", (formatted_date,formatted_time,0,0,0))
            conn.commit()
            cursor = c.execute("SELECT sum(jf) from jfen")
            row = cursor.fetchone()
            globals()['zjf'] = row[0]
            #获取总积分
            cursor = c.execute("SELECT jf from jfen order by jid desc limit 0,1")
            row = cursor.fetchone()
            globals()['jtjf'] = row[0]
            #获取今日积分
            cursor = c.execute("SELECT cid from record order by cid desc")
            row = cursor.fetchone()
            c.close()
            conn.close()
            globals()['cid'] = row[0]
            #提取cid到全局变量中
            globals()['testcs'] = 0
            #rid为0时,测试次数重计
            globals()['cuo_cs'] = 0
            #错误次数也重计
            globals()['begintime'] = time()
            #设定rid为0是的开始时间,可以计算做完16个汉字的时间
            globals()['njt'],globals()['njt1'],globals()['yshen'] = maxmin(xzng)
            #将年级和有声的变量按选择存入到全局变量
            globals()['ii'],globals()['hzid'],globals()['hz'],globals()['py'],globals()['zc1'],globals()['zc2'],globals()['zc3'],globals()['zc4'],globals()['zc5'],globals()['kw'],globals()['bs'],globals()['idsc']=set_all(globals()['njt'],globals()['njt1'])
            #将全部要用到的变量存入全局变量
            globals()['stime'] = time()
            #设定本次开始时间
            
            for i in range(1,(globals()['set_gz'] + 1)):
                if globals()['rongy'] != 1:
                    setattr(names['button_' + str(i)],"text",hz[ii[i-1]-1])
                else:
                    setattr(names['button_' + str(i)],"text",str(i)) #听写时不显示汉字,显示数字
                setattr(names['button_' + str(i)],"on_press",partial(bt1, hz[ii[i-1]-1]))
                #设置按键名称,即把汉字显示在按钮上,汉字通过随机错排列,这个ii就是打乱了的1到16顺序,2个-1是因为最小是0
            globals()['rid'] = 1
            #rid变为1,算第一次,答对了rid才会增加1
            globals()['duid'] = hzid[rid-1]
            #这个是对的汉字在数据库中的汉字
            globals()['jj'] = hz[rid-1]
            #这个变量是记忆对的汉字选择的按钮的编码,index是寻址,寻找rid在ii列中的位置,这个位置+1为按钮的参数
            if yshen == 0:
                if zc2[rid-1] == '':
                    c_value = py[rid-1] + " " + zc1[rid-1].replace(hz[rid-1],'□')
                else:
                    zc = []
                    zc.append(zc1[rid-1])
                    zc.append(zc2[rid-1])
                    if globals()['testtime'] == 1:#第一次显示拼音加2个组词
                        c_value = py[rid-1] + " " + zc1[rid-1].replace(hz[rid-1],'□') + "、" + zc2[rid-1].replace(hz[rid-1],'□')
                    elif globals()['testtime'] == 2:#第二次显示部首加1组词
                        c_value = py[rid-1] + " [" + bs[rid-1] + "] " + zc1[rid-1].replace(hz[rid-1],'□')
                    else:
                        c_value = "部首[" + bs[rid-1] + "] " + zc1[rid-1].replace(hz[rid-1],'□') + "、" + zc2[rid-1].replace(hz[rid-1],'□')
                    if zc3[rid-1] != '':
                        zc.append(zc3[rid-1])
                        if zc4[rid-1] != '':
                            zc.append(zc4[rid-1])
                        if zc5[rid-1] != '':
                            zc.append(zc5[rid-1])
                        zc = random.sample(zc,2)
                        if globals()['testtime'] == 1:#第一次显示拼音加2个组词
                            c_value = py[rid-1] + " " + zc[0].replace(hz[rid-1], '□')+ "、" + zc[1].replace(hz[rid-1],'□')
                        elif globals()['testtime'] == 2:#第二次显示拼音加1个组词
                            c_value = py[rid-1] + " [" + bs[rid-1] + "] " + zc[0].replace(hz[rid-1], '□')
                        else:#第三次不显示拼音,显示2个组词
                            c_value = "部首[" + bs[rid-1] + "] " + zc[0].replace(hz[rid-1], '□')+ "、" + zc[1].replace(hz[rid-1],'□')
            #无声是在输入栏显示拼音和隐去本字的组词,这里面采用随机数,在多个组词中随机选择2个
            c_text = '来自:' + kw[rid-1]
            #显示来自年级和课文
            c_label.text = c_text
            c_label3.text = tj_cs()
            #rid为0是,显示统计的4天学习情况
            if yshen == 0:
                c_input.value = c_value
            else:
                if zc4[rid-1] != '' and random.randint(0,1) == 0:
                    play_sound_backgrounda(hzid[rid-1],idsc[rid-1])
                else:
                    play_sound_background(hzid[rid-1],idsc[rid-1])
            #当选择有声时,用miniaudio发出声音,不使用sleep就不会播放声音,sleep的时长就是播放声音的时长,后台播放,虽然会重音但比较流畅
        #rid为0为一开始设置第一题
        else:
            text5 = ""
            if rid >=1:
                text5 = text5 + hz[rid-1] + "(" + py[rid-1] + ") " + zc1[rid-1] + " " + zc2[rid-1] + " " + zc3[rid-1] + " " + zc4[rid-1] + " " + zc5[rid-1]
            #text5是复习内容
            if testcs > 0:
                stext = '%d秒,共答%d题,错%d题,每题%d秒。' % (int(etime-begintime),testcs,cuo_cs,int((etime-begintime) / testcs))
            if xzng == globals()['jj']:
                if globals()['rongy'] == 1:
                    setattr(names['button_' + str(ii[rid-1])],"text",hz[rid-1])
                c_label1.text = "复习:" + text5
                abox.clear()
                image = toga.Image(str(giffolder.joinpath(str(hzid[rid-1]) + '.gif')))
                imageview = toga.ImageView(image=image,style=Pack(width=100, height=100, padding=10))
                abox.add(imageview)
                #回答正确才显示复习内容
                if yshen == 1:
                    c_input.value = hz[rid-1] + " [" + bs[rid-1] + "]√ (" + py[rid-1] + ") " + zc1[rid-1] + " " + zc2[rid-1] + " " + zc3[rid-1]
                    c_label2.text = '本轮学习' + stext
                else:
                    c_label2.text = '答对。本轮' + stext
                jf1 = kn + 6
                #原如果答题次数小于100,按100-次数后除以10取整为增加积分,取消直接加6分
                if yshen ==1:
                    jf1 = jf1 - 1
                else:
                    jf1 = jf1 + 2
                #无声模式积分加2分,有声减1分
                if globals()['set_gz'] == 25:
                    jf1 = jf1 + 2
                #25格再加2分
                jf1 = jf1 - (globals()['testtime'] - 1) * 2 #积分减去测试次数*2,即第二次-2分,第三次-4分
                if globals()['rongy'] != 1:
                    if ytime <= 3:
                        u_cs(4,hzid[rid-1])
                        jfen = jf1 + 4
                        u_jfen(jfen)
                        #用时小于3秒加4分
                    elif ytime > 3 and ytime <= 4:
                        u_cs(3,hzid[rid-1])
                        jfen = jf1 + 3
                        u_jfen(jfen)
                        #用时小于4秒加3分
                    elif ytime > 4 and ytime <= 5:
                        u_cs(2,hzid[rid-1])
                        jfen = jf1 + 2
                        u_jfen(jfen)
                        #用时小于5秒加2分
                    else:
                        u_cs(1,hzid[rid-1])
                        jfen = jf1 + 1
                        u_jfen(jfen)
                    #用时大于5秒加1分
                #play_sound_background(3500,1.174) 播放正确的声音
                globals()['stime'] = time()
                globals()['rid'] += 1
                #回答正确,开始下一个汉字的计时和rid
                if rid == (globals()['set_gz'] + 1):
                    if yshen != 0:
                        play_sound_background(4500,1.174)
                        sleep(1.1)
                    #切换16个字界面时,播放答对了,让孩子知道过篇了
                    u_record(testcs,cuo_cs,yshen,cid)
                    current_date = datetime.datetime.now()
                    formatted_date = current_date.strftime("%Y-%m-%d")
                    formatted_time = current_date.strftime("%H:%M:%S")
                    conn = sqlite3.connect(db_filepath, timeout=10, check_same_thread=False)
                    c = conn.cursor()
                    c.execute("INSERT INTO record (rq,sj,ts,ct,mt) VALUES (?,?,?,?,?);", (formatted_date,formatted_time,0,0,0))
                    conn.commit()
                    cursor = c.execute("SELECT sum(jf) from jfen")
                    row = cursor.fetchone()
                    globals()['zjf'] = row[0]
                    cursor = c.execute("SELECT jf from jfen where rq = '" + formatted_date + "' limit 0,1")
                    row = cursor.fetchone()
                    globals()['jtjf'] = row[0]
                    cursor = c.execute("SELECT cid from record order by cid desc")
                    row = cursor.fetchone()
                    globals()['cid'] = row[0] 
                    c.close()
                    conn.close()
                    globals()['testcs'] = 0
                    globals()['cuo_cs'] = 0
                    globals()['begintime'] = time()
                    njt = globals()['njt']
                    globals()['ii'],globals()['hzid'],globals()['hz'],globals()['py'],globals()['zc1'],globals()['zc2'],globals()['zc3'],globals()['zc4'],globals()['zc5'],globals()['kw'],globals()['bs'],globals()['idsc']=set_all(njt,globals()['njt1'])
                    globals()['stime'] = time()

                    for i in range(1,(globals()['set_gz'] + 1)):
                        if globals()['rongy'] != 1:
                            setattr(names['button_' + str(i)],"text",hz[ii[i-1]-1])
                        else:
                            setattr(names['button_' + str(i)],"text",str(i)) #听写时不显示汉字,显示数字
                        setattr(names['button_' + str(i)],"on_press",partial(bt1, hz[ii[i-1]-1]))
                    globals()['rid'] = 1
                    #当rid等于17是,实际就是第二轮开始,初始化一些变量,重新写入cid
                globals()['duid'] = hzid[rid-1]
                globals()['jj'] = hz[rid-1]
                #因为上面rid加1了,所以这2个全局变量都要变。
                if yshen == 0:
                    if zc2[rid-1] == '':
                        c_value = py[rid-1] + " " + zc1[rid-1].replace(hz[rid-1],'□')
                    else:
                        zc = []
                        zc.append(zc1[rid-1])
                        zc.append(zc2[rid-1])
                        if globals()['testtime'] == 1:#第一次显示拼音加2个组词
                            c_value = py[rid-1] + " " + zc1[rid-1].replace(hz[rid-1],'□') + "、" + zc2[rid-1].replace(hz[rid-1],'□')
                        elif globals()['testtime'] == 2:
                            c_value = py[rid-1] + " [" + bs[rid-1] + "] " + zc1[rid-1].replace(hz[rid-1],'□')
                        else:
                            c_value = "部首[" + bs[rid-1] + "] " + zc1[rid-1].replace(hz[rid-1],'□') + "、" + zc2[rid-1].replace(hz[rid-1],'□')
                        if zc3[rid-1] != '':
                            zc.append(zc3[rid-1])
                            if zc4[rid-1] != '':
                                zc.append(zc4[rid-1])
                            if zc5[rid-1] != '':
                                zc.append(zc5[rid-1])
                            zc = random.sample(zc,2)
                            if globals()['testtime'] == 1:#第一次显示拼音加2个组词
                                c_value = py[rid-1] + " " + zc[0].replace(hz[rid-1], '□')+ "、" + zc[1].replace(hz[rid-1],'□')
                            elif globals()['testtime'] == 2:#第二次显示拼音加1个组词
                                c_value = py[rid-1] + " [" + bs[rid-1] + "] " + zc[0].replace(hz[rid-1], '□')
                            else:#第三次显示拼音,显示2个组词
                                c_value = "部首[" + bs[rid-1] + "] " +zc[0].replace(hz[rid-1], '□')+ "、" + zc[1].replace(hz[rid-1],'□')
                if yshen == 0:
                    c_input.value = c_value
                else:
                    if zc4[rid-1] != '' and random.randint(0,1) == 0:
                        play_sound_backgrounda(hzid[rid-1],idsc[rid-1])
                    else:
                        play_sound_background(hzid[rid-1],idsc[rid-1])
            #上面为选择正确时的程序
            else:
                globals()['cuo_cs'] += 1
                if globals()['rongy'] == 1:
                    setattr(names['button_' + str(ii[rid-1])],"text",hz[rid-1])
                c_label1.text = "提示:" + text5
                if yshen == 1:
                    c_input.value = "答错了!请重新选择!"
                    c_label2.text = '累计学习' + stext
                    play_sound_background(3500,1.325)
                    sleep(1.2)
                    #播放错误的声音,还是需要sleep,不然不会停下来
                    if zc4[rid-1] != '' and random.randint(0,1) == 0:
                        play_sound_backgrounda(hzid[rid-1],idsc[rid-1])
                    else:
                        play_sound_background(hzid[rid-1],idsc[rid-1])
                    #选择错误时的程序,重新读一遍
                else:
                    if zc2[rid-1] == '':
                        c_value = py[rid-1] + " [" + bs[rid-1] + "] " + zc1[rid-1].replace(hz[rid-1],'□')
                    else:
                        zc = []
                        zc.append(zc1[rid-1])
                        zc.append(zc2[rid-1])
                        c_value = py[rid-1] + " [" + bs[rid-1] + "] " + zc1[rid-1].replace(hz[rid-1],'□') + "、" + zc2[rid-1].replace(hz[rid-1],'□')
                        if zc3[rid-1] != '':
                            zc.append(zc3[rid-1])
                            if zc4[rid-1] != '':
                                zc.append(zc4[rid-1])
                            if zc5[rid-1] != '':
                                zc.append(zc5[rid-1])
                            zc = random.sample(zc,2)
                            c_value = py[rid-1] + " [" + bs[rid-1] + "] " + zc[0].replace(hz[rid-1], '□')+ "、" + zc[1].replace(hz[rid-1],'□')
                    c_input.value = "重答:" + c_value
                    c_label2.text = '答错!累计' + stext
                if globals()['rongy'] != 1:
                    j_cs(5,hzid[rid-1])
                    jfen = -6
                    u_jfen(jfen)
                    #选择错误,扣6分
                globals()['stime'] = time()
            if globals()['rongy'] != 1:
                if jfen > 0:
                    c_text = '总分:' + str(zjf) + ',今日:' + str(jtjf) + ',本题获得' + str(jfen) +'分。来自:' + kw[rid-1]
                else:
                    c_text = '总分:' + str(zjf) + ',今日:' + str(jtjf) + ',本题扣' + str(abs(jfen)) +'分。来自:' + kw[rid-1]
            else:
                c_text = '总分:' + str(zjf) + ',今日:' + str(jtjf) + ',来自:' + kw[rid-1]
            c_label.text = c_text
            c_label3.text = tj_cs()
        if globals()['cid'] > 0:
            u_record(testcs,cuo_cs,yshen,cid)
            u_cs1(hzid[rid-1])
        #记录学习情况
        
    if globals()['set_gz'] == 16:
        aaa = '一 二 三 四 五 六 无 声 ㈠ ㈡ ㈢ ㈣ ㈤ ㈥ 16 25'.split()
        for i in range(1,17):
            names['button_' + str(i)] = toga.Button(aaa[i-1], on_press=partial(bt1, str(i)),style=Pack(font_size=28))
    else:
        aaa = '一 二 三 四 五 六 无 声 ㈠ ㈡ ㈢ ㈣ ㈤ ㈥ 16 25 ㈠ ㈡ ㈢ ㈣ ㈤ ㈥ 听 写 用'.split()
        for i in range(1,26):
            names['button_' + str(i)] = toga.Button(aaa[i-1], on_press=partial(bt1,str(i)),style=Pack(font_size=25))
    #用set_g参数控制16格和25格的初始界面
    # 设置组件样式和布局
    c_box.add(c_input)
    box.add(c_box)
    if globals()['set_gz'] == 16:
        for i in range(1,5):
            b1_box.add(names['button_' + str(i)])
        for i in range(5,9):
            b2_box.add(names['button_' + str(i)])
        for i in range(9,13):
            b3_box.add(names['button_' + str(i)])
        for i in range(13,17):
            b4_box.add(names['button_' + str(i)])
    else:
        for i in range(1,6):
            b1_box.add(names['button_' + str(i)])
        for i in range(6,11):
            b2_box.add(names['button_' + str(i)])
        for i in range(11,16):
            b3_box.add(names['button_' + str(i)])
        for i in range(16,21):
            b4_box.add(names['button_' + str(i)])
        for i in range(21,26):
            b5_box.add(names['button_' + str(i)])
    abox.add(imageview)
    
    box.add(b1_box)
    box.add(b2_box)
    box.add(b3_box)
    box.add(b4_box)
    if globals()['set_gz'] == 25:
        box.add(b5_box)
    box.add(c_label)
    box.add(c_label1)
    box.add(c_label2)
    box.add(c_label3)
    bigbox.add(box)
    bigbox.add(abox)
    # 设置 outer box 和 inner box 的样式
    box.style.update(direction=COLUMN, padding=4)
    abox.style.update(direction=COLUMN, padding=1)
    bigbox.style.update(direction=ROW, padding=1)
    b1_box.style.update(direction=ROW, padding=1)
    b2_box.style.update(direction=ROW, padding=1)
    b3_box.style.update(direction=ROW, padding=1)
    b4_box.style.update(direction=ROW, padding=1)
    if globals()['set_gz'] == 25:
        b5_box.style.update(direction=ROW, padding=1)
    c_box.style.update(direction=ROW, padding=5)

    # 设置单个组件的样式
    c_input.style.update(width=345, flex=1)

    # button.style.update(padding=15)

    c_label.style.update(width=345, padding_left=4)
    c_label1.style.update(width=345, padding_left=4)
    c_label2.style.update(width=345, padding_left=4)
    c_label3.style.update(width=345, padding_left=4)
    
    if globals()['set_gz'] == 16:
        for i in range(1,17):
            names['button_' + str(i)].style.update(width=85, height=85, padding=1, background_color='white')
    else:
        for i in range(1,26):
            names['button_' + str(i)].style.update(width=68, height=68, padding=1, background_color='white')
    
    return bigbox
def play_sound_background(hzid,idsc):
    thread = threading.Thread(target=bfsy, args=(hzid,idsc,))
    thread.daemon = True
    thread.start()
def play_sound_backgrounda(hzid,idsc):
    thread = threading.Thread(target=bfsya, args=(hzid,idsc,))
    thread.daemon = True
    thread.start()

#用线程,在后台播放声音
def main():
    return toga.App(globals()['app_name'], "org.qwrz2", startup=build)

if __name__ == "__main__":
    main().main_loop()

附注:用beeware生成安卓app时,gif动画不能正常显示,这个问题待解决;另外用60个线程来提醒做题的做法我自己觉得很low。

附上win版安装程序,如果感兴趣可以与我索要安卓app。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值