歡迎關(guān)注我的專欄( つ??ω??)つ【人工智能通識(shí)】
【專題】簡(jiǎn)書下載器:Python-Tkinter項(xiàng)目編程入門
自定義模塊導(dǎo)入
如果我們需要在a.py文件中導(dǎo)入c文件夾下b.py的內(nèi)容(函數(shù)和變量等),比如希望使用from c.b import *這樣的語(yǔ)句,那么就需要先在b.py所在的文件夾創(chuàng)建一個(gè)init.py文件(即使是空的也可以)。
比如下圖,我們?cè)趍ain.py文件同級(jí)創(chuàng)建了modules文件夾,然后里面創(chuàng)建了reqs.py文件。

然后我們就可以在main.py內(nèi)使用下面的代碼引入reqs.py的內(nèi)容了。
from modules.reqs import * # 導(dǎo)入reqs請(qǐng)求函數(shù)
這種模式導(dǎo)入的reqs.py中的變量可以直接使用,不需要使用任何處理。
自動(dòng)計(jì)時(shí)更新Label文字
我們可以用Tkinter很方便的創(chuàng)建一個(gè)標(biāo)簽元素:
info=ttk.Label(root, text = '?/?')
info.grid(row = 3, column = 1, padx = 10, ipady = 10, ipadx = 10, sticky = E)
如何動(dòng)態(tài)改變標(biāo)簽的文字?可以使用Tkinter的StringVar變量字符串,比如先創(chuàng)建一個(gè)varStr=StringVar(),然后設(shè)定textvariable = varStr這樣的代碼來(lái)代替text='xx',當(dāng)使用varStr.set('AAA')的時(shí)候,標(biāo)簽文字會(huì)自動(dòng)更新為AAA。(可以參考后面關(guān)于cookieStr的代碼)
如果我們要定時(shí)(比如每隔0.5秒)刷新改變這里的text文字,就要用到計(jì)時(shí)器了。
info.after(500, refreshInfo) #自動(dòng)循環(huán)更新
這里的after是延遲運(yùn)行的意思,500毫秒之后運(yùn)行refreshInfo這個(gè)函數(shù),這個(gè)函數(shù)的代碼如下(要放在這一行前面才行):
def refreshInfo():
info.config(text=genInfoStr())
info.after(500, refreshInfo)
這里我們看到了自身循環(huán)調(diào)用自身的用法info.after(500, refreshInfo),這樣實(shí)現(xiàn)循環(huán)。info.config(text=genInfoStr())這是修改標(biāo)簽文字的方法,genInfoStr()是來(lái)自reqs.py的函數(shù),它返回一個(gè)字符串。
界面布局
初步設(shè)計(jì)界面包含兩個(gè)輸入框,分別讓用戶輸入Cookie和簡(jiǎn)書的賬戶名,點(diǎn)擊按鈕開(kāi)始下載,下載的過(guò)程中用黑白格顯示進(jìn)程。

多線程
Tkinter界面程序?qū)⒛J(rèn)占用主線程,如果我們要定時(shí)刷新下載進(jìn)度條,那么就必須另外啟動(dòng)一個(gè)單獨(dú)的線程,否則就會(huì)阻塞主線程,導(dǎo)致不刷新。
啟動(dòng)一個(gè)線程的代碼是:
t = Thread(target=getArticles, args=(cookiestr,)) # 多線程,避免鎖死界面
t.start()
這里的target是要運(yùn)行的函數(shù),args是指定給這個(gè)函數(shù)的參數(shù)。
reqs.py文件代碼
import time
from threading import Thread
atotal = 32 # 總文章數(shù)量
afini = 0 # 已讀取的文章數(shù)量
cookiestr = '' # cookie全局變量
def genInfoStr(): # 拼接信息字符串
global atotal
global afini
infoStr = '正在獲取('+str(afini)+'/'+str(atotal)+'):'
per = int(atotal/15)
fi = int(afini/per)
for _ in range(fi):
infoStr += '■'
for _ in range(15-fi):
infoStr += '□'
return infoStr
def getAll(cookieStr): # 獲取全部
t = Thread(target=getArticles, args=(cookiestr,)) # 多線程,避免鎖死界面
t.start()
return 'getAll OK!'
def getImages(): # 獲取圖片列表
return 'getImages OK!'
def getArticles(cookiestr): # 獲取文章內(nèi)容
global afini
for _ in range(10):
afini += 1
time.sleep(1)
return 'getArticles OK!'
def getArticlesList(): # 獲取文章列表
return 'getArticlesList OK!'
def getVolums(): # 獲取文集列表
return 'getVolums OK!'
這里定義了很多獲取簡(jiǎn)書文章相關(guān)接口的函數(shù),先獲取文集getVolums,再獲取文章列表getArticlesList,再獲取文章內(nèi)容getArticles,再獲取相關(guān)圖片getImages,而這些的入口是獲取全部getAll,這只是個(gè)框架,幫助梳理思路,以后再具體調(diào)整。
genInfoStr產(chǎn)生信息標(biāo)簽的字符串,它利用atotal總文章數(shù)和afini完成文章數(shù)計(jì)算得到界面上標(biāo)簽的文字內(nèi)容。
注意我們?cè)賕etArticles函數(shù)中臨時(shí)設(shè)定了計(jì)數(shù)器自增afini完成的文章數(shù)量。
main.py
from tkinter import *
from tkinter import ttk
from modules.reqs import * # 導(dǎo)入reqs請(qǐng)求函數(shù)
import time
import random
# 創(chuàng)建窗體
root = Tk()
root.title('MyApp')
root.resizable(width=False, height=False)
root.config(background='#EEE')
root.geometry('500x240')
# 啟動(dòng)獲取動(dòng)作
def run():
getAll(cookieStr)
# 信息的自刷新函數(shù)
def refreshInfo():
info.config(text=genInfoStr())
info.after(500, refreshInfo)
# ---創(chuàng)建界面
ttk.Frame(root, height=20).grid()
rown=0
# Cookie輸入框
rown+=1
cookieStr = StringVar()
cookieStr.set('請(qǐng)?jiān)谶@里粘貼瀏覽器中的Cookie字段')
iptCookie = ttk.Entry(root, textvariable=cookieStr)
iptCookie.grid(
row=rown, column=1, pady=10, padx=10, ipady=5, sticky='WE')
# 賬戶名輸入框
rown+=1
nameStr=StringVar()
nameStr.set('請(qǐng)輸入您的簡(jiǎn)書賬戶名')
iptName = ttk.Entry(root, textvariable=nameStr)
iptName.grid(
row=rown, column=1, pady=10, padx=10, ipady=5, sticky='WE')
# 運(yùn)行按鈕
rown+=1
bt = ttk.Button(root, text='開(kāi)始下載', width=30, command=run)
bt.grid(
row=rown, column=1, padx=10, ipady=10, ipadx=10, sticky=E)
# 信息標(biāo)簽
rown+=1
info = ttk.Label(root, text='?/?')
info.grid(row=rown, column=1, padx=10, ipady=10, ipadx=10, sticky=E)
info.after(500, refreshInfo) # 自動(dòng)循環(huán)更新
root.mainloop()
在這里我們直接從run方法呼叫reqs中的getAll方法,這個(gè)getAll方法會(huì)啟動(dòng)單獨(dú)線程getArticles,每隔1秒就自增一個(gè)afini,同時(shí)info.after會(huì)每隔0.5秒調(diào)用reqs中的genInfoStr函數(shù),而這個(gè)genInfoStr函數(shù)會(huì)根據(jù)實(shí)時(shí)的atotal和afini來(lái)拼合文字進(jìn)度條。
迄今為止,我們實(shí)現(xiàn)了簡(jiǎn)單的界面布局、界面元素觸發(fā)函數(shù)、函數(shù)自動(dòng)化更新界面、多線程調(diào)用以及分拆代碼文件導(dǎo)入自定義模塊等功能。
整體上的框架已經(jīng)具備了,后續(xù)我們正式進(jìn)入數(shù)據(jù)下載相關(guān)的業(yè)務(wù)流程代碼。
歡迎關(guān)注我的專欄( つ??ω??)つ【人工智能通識(shí)】
每個(gè)人的智能新時(shí)代
如果您發(fā)現(xiàn)文章錯(cuò)誤,請(qǐng)不吝留言指正;
如果您覺(jué)得有用,請(qǐng)點(diǎn)喜歡;
如果您覺(jué)得很有用,歡迎轉(zhuǎn)載~
END