1. 程式人生 > >pyqt5 tablewidget 利用執行緒動態重新整理資料

pyqt5 tablewidget 利用執行緒動態重新整理資料

問題

知道要用執行緒,所以就先嚐試寫了一個執行緒,然後每次都獲取資料,然後直接通過這種方法來朝table裡面更新資料。

#python程式碼
table=MainWindow_ui.tableWidget_2
table.setItem(i,0,QtWidgets.QTableWidgetItem(str(jcb.Name)))

發現數據並不是想象中跟執行緒執行那樣實時的,要點一下才能顯示出資料來
並且還會出現一些問題

問題圖片

為了做出對比,我將作業名的表格填寫改成table.setItem的方式,其他格子用訊號量機制,可以很清楚的看到問題所在!!!!
這裡寫圖片描述

解決方法

核心是要通過qt的槽函式來發射訊號告知qt視窗的元件來進行更新,如果是直接程式上來“發射接受”訊號,而不通過qt的槽函式來弄就會出現問題

thread函式

原本class裡面自己寫的是一個python的threading包的執行緒,利用threading.Event()來進行程序阻塞,沒想到直接修改成
QtCore.QThread,兩個混合在一起也能用。。。

class Job(QtCore.QThread):#注意這裡使用的是qt自己本身的執行緒,而不能用python自己的執行緒
    signal2=QtCore.pyqtSignal(tuple)#因為這個訊號槽要繼承於Qobject,不然會發生沒有emit,connect函式的報錯,括號裡面填寫的是發射的資料型別
    def signal2emit
(self,var:tuple):
self.signal2.emit(var)#朝connect的函式發射一個tuple def __init__(self, *args, **kwargs):#這裡自己實現 super(Job, self).__init__(*args, **kwargs) self.__flag = threading.Event() # 用於暫停執行緒的標識 self.__flag.set() # 設定為True self.__running = threading.Event() # 用於停止執行緒的標識
self.__running.set() # 將running設定為True self.signal2.connect(setItem)#連線發射函式 def run(self): global SystemTime,TimePice#宣告要用的全域性變數 while self.__running.isSet():#如果被設定為了true就繼續,false就終止了 self.__flag.wait() # 為True時立即返回, 為False時阻塞直到內部的標識位為True後返回 ################### #這裡寫執行緒要乾的事情# ################### time.sleep(1) def pause(self): self.__flag.clear() # 設定為False, 讓執行緒阻塞 def resume(self): self.__flag.set() # 設定為True, 讓執行緒停止阻塞 def stop(self): self.__flag.set() # 將執行緒從暫停狀態恢復, 如何已經暫停的話 self.__running.clear() # 設定為False

setItem函式,接受訊號量

def setItem(var:tuple):#用於向jcb表格填寫內容
    i=var[0]#行
    j=var[1]#列
    s=var[2]#值
    table=MainWindow_ui.tableWidget_2
    if j != 6 :
        table.setItem(i,j,QtWidgets.QTableWidgetItem(str(s)))
    else :
        table.cellWidget(i,6).setValue(s)#這是個進度條來的

朝表格中填寫資料的函式

這是放在主執行緒中該乾的事情的一部分
其中註釋掉的部分就是之前直接朝表格中set資料的部分,這是不行的,要通過Qthread來發射訊號量

def Print_Job():
    rowcol=len(Jcb_Ready_List)+len(Jcb_Wait_List)
    print(rowcol)
    #MainWindow_ui.tableWidget_2.setRowCount(rowcol)
    for i in range(0,rowcol):
        MainWindow_ui.tableWidget_2.showRow(i)
    #for i in range(rowcol,100):
    #    MainWindow_ui.tableWidget_2.hideRow(i)
    for i in range(0,len(Jcb_Ready_List)):
        jcb=Jcb_Ready_List[i]
        table=MainWindow_ui.tableWidget_2
                                         #table.setItem(i,0,QtWidgets.QTableWidgetItem(str(jcb.Name)))
        MainThread.signal2emit((i,0,jcb.Name))
        #table.setItem(i,1,QtWidgets.QTableWidgetItem(str(jcb.Arrival_time)))
        MainThread.signal2emit((i,1,jcb.Arrival_time))
        #table.setItem(i,2,QtWidgets.QTableWidgetItem(str(jcb.Need_memory)))
        MainThread.signal2emit((i,2,jcb.Need_memory))
        #table.setItem(i,3,QtWidgets.QTableWidgetItem(str(jcb.Need_time)))
        MainThread.signal2emit((i,3,jcb.Need_time))
        #table.setItem(i,4,QtWidgets.QTableWidgetItem(str(jcb.Already_execution_time)))
        MainThread.signal2emit((i,4,jcb.Already_execution_time))
        #table.setItem(i,5,QtWidgets.QTableWidgetItem(str(jcb.Wait_time)))
        MainThread.signal2emit((i,5,jcb.Wait_time))
        #bar:QtWidgets.QProgressBar=MainWindow_ui.tableWidget_2.cellWidget(i,6)
        #bar.setValue(100-jcb.Need_time/(jcb.Already_execution_time+jcb.Need_time)*100)
        MainThread.signal2emit((i,6,100-jcb.Need_time/(jcb.Already_execution_time+jcb.Need_time)*100))

成果

這樣就順利實現了table widget的動態更新資料
這裡寫圖片描述