天天看點

Pyqt5 多線程 檔案搜尋用Pyqt5實作多線程檔案搜尋

用Pyqt5實作多線程檔案搜尋

我學Java的時候也用Swing做了一個檔案搜尋的小程式,但界面真的挺醜的,現在學了點python,感覺python是最簡單的語言,沒有之一。 (大家沒事都可以來學的,真的很簡單有趣哦)

我采用的是pyqt5,是以需要先安裝Pyqt5子產品

直接cmd指令輸入
pip install pyqt5
           

閑言少叙,上代碼!!

# -*- coding: utf-8 -*-
# @Time    : 2018\9\15 20:39
# @Author  : Tang weiyang
# @File    : FileSearch02.py
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon
import sys
import os
import threading

class fileSearchThread(QThread):
    sinOut = pyqtSignal(str)
    # 自定義信号,執行run()函數時,從相關線程發射此信号

    def __init__(self,key):
        super().__init__()
        self.key = key

    def run(self):
        threads=[]
        path = [r"c:\\", r"d:\\", r"e:\\", r"f:\\"]
        #通過多線程對windows下的多個盤符進行檔案的周遊查找
        for each in path:
            t = threading.Thread(target=self.search, args=(self.key,each,))
            threads.append(t)
            t.start()

        for i in range(len(threads)): #将主線程阻塞
            threads[i].join()
        print("搜尋結束")

    def search(self,keyword, path):
        for dirpath, dirnames, filenames in os.walk(path):
            for filename in filenames:
                if filename.__contains__(keyword):
                    print(os.path.join(dirpath, filename))
                    self.sinOut.emit(os.path.join(dirpath, filename))
            for folder in dirnames:
                if folder.__contains__(keyword):
                    print(os.path.join(dirpath,folder))
                    self.sinOut.emit(os.path.join(dirpath,folder))


class fileSearch(QListWidget):

    def __init__(self):
        super().__init__()
        self.Ui()

    def Ui(self):
        self.key= QLineEdit()
        self.bt=QPushButton("搜尋")
        self.result = QListWidget()

        self.bt.clicked.connect(self.ButtonClicked) #按鈕單擊信号綁定到槽
        # self.line.editingFinished.connect(self.Action)
        self.key.editingFinished.connect(self.ButtonClicked)

        grid = QGridLayout()
        grid.setSpacing(10)  # 建立标簽之間的空間

        grid.addWidget(self.key, 1, 0)  # (1,0)表示顯示的位置
        grid.addWidget(self.bt, 1, 1)
        grid.addWidget(self.result, 2, 0, 5, 2)  # 指定元件的跨行和跨列的大小,指定這個元素跨5行顯示

        self.setLayout(grid)
        for i in range(1,100):
            self.result.addItem("搜尋"+str(i)+"個項目")

        self.result.itemClicked.connect(self.Clicked)

        self.setGeometry(300, 300, 500, 500)
        self.setWindowTitle('檔案搜尋')
        self.setWindowIcon(QIcon('icon.jpg'))
        self.show()

    def Clicked(self, item):
        QMessageBox.information(self, "ListWidget", "You clicked: " + item.text())
        os.startfile(item.text()) #打開檔案

    def ButtonClicked(self):
        # 建立新線程,将自定義信号sinOut連接配接到slotAdd()槽函數
        keyword = self.key.text()
        self.result.clear()
        self.thread=fileSearchThread(keyword)
        self.thread.sinOut.connect(self.slotAdd)
        self.thread.start()

    def slotAdd(self,filename):

        self.result.addItem(str(filename))


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = fileSearch()
    sys.exit(app.exec_())

           

這個小程式可以搜尋本地所有的檔案,時間大概在10秒左右,點選檔案的位址,就可以打開這個檔案.多線程這個有點卡殼,然後寫的很變扭.

這個小程式還有一個小感悟:

  1. 涉及到GUI的程式最好要将UI界面和資料處理(還包括大批量檔案的讀取,循環計算),否則會導緻UI界面無響應,這一點可以參考我的代碼,通過一個多線程很好解決這個問題
  2. 線程之間的資訊傳遞,可以通過信号和槽完成,
sinOut = pyqtSignal(str) #自定義一個信号槽

self.thread.sinOut.connect(self.slotAdd)#信号綁定到槽

self.sinOut.emit(os.path.join(dirpath,folder)) #發射信号
           
  1. pyqt的布局真的很好用,GridLayout真的超級好用

    效果圖如下

    Pyqt5 多線程 檔案搜尋用Pyqt5實作多線程檔案搜尋