【編程】Tkinter界面交互控制

歡迎關(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容