PyQt5多線程編程

單位的公共儀器需要預(yù)約才能夠使用包券,但是自從預(yù)約時間改到了早上介袜,就很不好約了痹兜,所以決定寫一個程序?qū)崿F(xiàn)自動預(yù)約蛮粮。由于還要分享給實驗室其它同學(xué)使用益缎,就得寫一個GUI了,這一下代碼量瞬間變成了原來的10倍蝉揍,不過學(xué)到了些新東西链峭,這波不虧。

在圖形化編程中一個很重要的一點就是使用多線程又沾,將UI線程獨立出來弊仪。如果你的程序不存在會造成線程阻塞的操作熙卡,不使用多線程倒也沒什么大問題,但是如果存在像聯(lián)網(wǎng)励饵、讀寫文件等可能需要等待的操作驳癌,使用單線程就可能會造成UI假死,這對于用戶體驗來說是非常不友好的役听。例如微軟的office套件為了兼容老式CPU颓鲜,IO等操作都是使用的UI的線程,打開或保存大文件時典予,用戶界面無響應(yīng)甜滨;而像photoshop這樣的程序由于使用了多線程,即使有大量的IO行為瘤袖,UI也可以響應(yīng)用戶的操作衣摩。

Qt引以為豪的對象通訊機制被稱為信號-槽(signal-slot)機制。當(dāng)特定事件被觸發(fā)時(如子線程結(jié)束)將發(fā)送一個信號捂敌,而與該信號建立的連接槽艾扮,則可以接收到該信號并做出反應(yīng)(根據(jù)子線程的返回值執(zhí)行操作)。

在我的程序中占婉,需要在儀器開放預(yù)約前不斷查詢泡嘴,在開放預(yù)約的第一刻立即提交表單,而為了不拖垮服務(wù)器逆济,需要在每次查詢后讓線程休眠一會酌予。如果所有這些操作都在主線程中完成,那么線程休眠的時候UI就會無響應(yīng)纹腌,在我的程序中就表現(xiàn)為點擊開始查詢后UI就一直處于無響應(yīng)狀態(tài)霎终,直到預(yù)約成功后才恢復(fù)響應(yīng)。

因此升薯,就需要新建一個線程莱褒,這個線程只用來發(fā)送信號調(diào)用查詢函數(shù),發(fā)送完畢后即休眠涎劈,等待下一次發(fā)送或任務(wù)完成后結(jié)束線程广凸。

靈魂畫手的流程圖

要創(chuàng)建一個新線程,需要在程序中定義一個類蛛枚,這個類要繼承QtCore.QThread谅海,然后把要執(zhí)行的操作放進run()函數(shù)中,線程啟動后蹦浦,就會自動運行這個函數(shù)扭吁。結(jié)束線程時通過調(diào)用線程的terminate()方法來中止線程:

class QueryWaitThread(QtCore.QThread):
    # 定義線程需要用到的信號
    query_signal = QtCore.pyqtSignal()      # 查詢信號
    on_complete = QtCore.pyqtSignal(int)    # 每次查詢完成時發(fā)送,可以發(fā)送參數(shù),
                                                此處參數(shù)int為查詢次數(shù)
    terminate_thread = QtCore.pyqtSignal()  # 結(jié)束線程信號

    def __init__(self):
        super(QueryWaitThread, self).__init__()

    def run(self): # 只發(fā)送信號侥袜,然后休眠蝌诡。
        i = 1
        while True:
            self.on_complete.emit(i)        # 調(diào)用信號的emit()方法
            i += 1
            self.query_signal.emit()
            sleep(60)

    def kill_thread(self):
        self.terminate()

我的查詢函數(shù)與驗證函數(shù):

def auto_query(self):
    ################
    #    查詢操作   #
    ################
    if self.good_to_submit():
        self.btnstop.hide()
        self.btn_resel.show()
        main.Appoint(self)

def good_to_submit(self):
    if # 還無法提交表單:
        return False
    self.T.terminate_thread.emit() # 驗證可以提交表單后發(fā)送中止信號
    return True

def print_current_count(self, i):
    self.normalOutputWritten("當(dāng)前為第 %i 次查詢...\n" % i)

self.normalOutputWritten()是一個我自己定義的函數(shù),用于在窗體的文本框中打印信息枫吧,你也可以定義自己的這類函數(shù)浦旱。

定義好信號以后,接下來需要調(diào)用信號的connect()方法將信號連接到需要執(zhí)行函數(shù)上九杂。下面的start()stop()是窗體按鈕按下后執(zhí)行的操作颁湖,我們在這兩個函數(shù)中使用剛剛定義好的信號:

def start(self):
    ################
    # do something #
    ################
    self.T = QueryWaitThread()
    self.T.query_signal.connect(self.auto_query)
    self.T.on_complete.connect(self.print_current_count)
    self.T.terminate_thread.connect(self.T.kill_thread)
    self.normalOutputWritten("已開啟自動查詢,當(dāng)有符合條件的時間段時將自動提交預(yù)約...\n")
    self.T.start()  # 開始執(zhí)行線程函數(shù)
    self.btnstop.show()
    self.btn_resel.hide()

def stop(self):
    self.btnstop.hide()
    self.btn_resel.show()
    self.T.terminate_thread.emit() # 發(fā)送中止信號
    self.normalOutputWritten("用戶終止查詢例隆。\n")

當(dāng)按下開始按鈕后甥捺,程序會構(gòu)造出一個線程T,執(zhí)行到T.start()后镀层,其中的run()函數(shù)便會進入while循環(huán)涎永,不斷發(fā)送查詢信號,直到good_to_submit()函數(shù)返回True表明已經(jīng)可以提交表單鹿响,或者當(dāng)停止按鈕按下后終止。

改進后的程序只是將定時功能分離了出來谷饿,實際上聯(lián)網(wǎng)查詢功能還是使用主線程完成的惶我,在程序等待服務(wù)器返回數(shù)據(jù)的過程中UI還是會有短暫的無響應(yīng)時間,不過這是在用戶點擊后產(chǎn)生的博投,因此對體驗影響不大绸贡。但是,嚴格來說聯(lián)網(wǎng)也應(yīng)該分離出一個線程毅哗,畢竟服務(wù)器有時候返回會很慢听怕,這時候如果你的用戶是一個暴躁老哥,還是會對體驗有影響的虑绵。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載尿瞭,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末翅睛,一起剝皮案震驚了整個濱河市声搁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捕发,老刑警劉巖疏旨,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異扎酷,居然都是意外死亡檐涝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谁榜,“玉大人幅聘,你說我怎么就攤上這事《枧溃” “怎么了喊暖?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長撕瞧。 經(jīng)常有香客問我陵叽,道長,這世上最難降的妖魔是什么丛版? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任巩掺,我火速辦了婚禮,結(jié)果婚禮上页畦,老公的妹妹穿的比我還像新娘胖替。我一直安慰自己,他們只是感情好豫缨,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布独令。 她就那樣靜靜地躺著,像睡著了一般好芭。 火紅的嫁衣襯著肌膚如雪燃箭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天舍败,我揣著相機與錄音招狸,去河邊找鬼。 笑死邻薯,一個胖子當(dāng)著我的面吹牛裙戏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播厕诡,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼累榜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了木人?” 一聲冷哼從身側(cè)響起信柿,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎醒第,沒想到半個月后渔嚷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡稠曼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年形病,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡漠吻,死狀恐怖量瓜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情途乃,我是刑警寧澤绍傲,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站耍共,受9級特大地震影響烫饼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜试读,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一杠纵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钩骇,春花似錦比藻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至纽匙,卻和暖如春群凶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哄辣。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赠尾,地道東北人力穗。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像气嫁,于是被迫代替她去往敵國和親当窗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容