我正在處理我的第一個應用程式。在一個視窗中,我有一個按鈕,單擊該按鈕后,我想從另一個模塊執行一個方法。此方法需要不確定的時間來執行,并且取決于終端中的用戶輸入。此方法創建一個檔案并重復打開它,將內容寫入檔案,然后關閉檔案。在運行的同時,我在視窗中有一個 matplotlib 圖形小部件,其中包含一個繪圖,每次通過讀取和繪制檔案最新行中的資料將新內容寫入檔案時,我都想更新該繪圖。
據我了解,如果我在 QT 程式的主執行緒中運行它,則在用戶輸入函式完成之前,我的應用程式中的任何內容都不會回應。為了解決這個問題,我嘗試將用戶輸入法的執行移到作業執行緒中。以我這樣做的方式,我不相信它正在起作用。作為測驗,我嘗試制作一個 QTimer,它嘗試讀取檔案并每秒繪制一次(添加一些內容來檢查檔案是否存在)。這將列印檔案在長任務之前還不存在,然后什么都不做,直到長任務完成然后開始每秒讀取和繪制檔案。我不確定這是否意味著我沒有正確地進行執行緒處理,或者是否正在發生其他事情。
為了檢查檔案的更改,我嘗試使用 QFileSystemWatcher。更新:現在,當 userInputFunction() 運行時什么也沒有發生,但是當它完成時我得到“data/runName_Rec.txt dataFileCreated”。如果我然后以任何方式手動編輯檔案,繪圖就會發生。但我仍然想正確地將其執行緒化,以便在我運行 userInputFunction() 時觀察者作業
這是我的代碼相關部分的簡化示例。對于任何糟糕的風格問題,我們深表歉意。
from PyQt5 import QtWidgets, uic, QtCore, QtGui
from pyqtgraph import PlotWidget
from PyQt5.QtCore import QObject, QThread, pyqtSignal
import pyqtgraph as pg
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog, QMainWindow
import os
from os.path import exists
import csv
import numpy as np
import pandas as pd
import myModule
dirname = os.path.dirname(__file__)
class Worker(QObject):
finished = pyqtSignal()
def run(self,param1,param2):
"""Long-running task with user input from terminal."""
myModule.userInputFunction(param1,param2)
self.finished.emit()
class someWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(someWindow, self).__init__(*args, **kwargs)
#Load the UI Page
uic.loadUi('somewindow.ui', self)
self.directoryPath = "data"
self.fs_watcher = QtCore.QFileSystemWatcher()
self.fs_watcher.addPath(self.directoryPath)
self.fs_watcher.directoryChanged.connect(self.dataFileCreated)
self.StartScanButton.clicked.connect(self.startSliceScan)
self.EndScanButton.clicked.connect(self.endScan)
def dataFileCreated(self):
self.filePath = os.path.join(dirname, "data/" self.runNameBox.toPlainText() "_Rec.txt")
print(self.filePath " dataFileCreated")
self.fs_watcher.addPath(self.filePath)
self.fs_watcher.fileChanged.connect(self.update_graph)
def update_graph(self):
if exists(self.path):
print("file exists!")
#then read the filePath.txt and plots the data
else:
print("file doesn't exist yet")
def endScan(self):
#change some display things
def runLongTask(self):
# Step 2: Create a QThread object
self.thread = QThread()
# Step 3: Create a worker object
self.worker = Worker()
# Step 4: Move worker to the thread
self.worker.moveToThread(self.thread)
# Step 5: Connect signals and slots
self.thread.started.connect(self.worker.run(param1,param2))
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.thread.finished.connect(self.thread.deleteLater)
# Step 6: Start the thread
self.thread.start()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = someWindow()
w.show()
sys.exit(app.exec_())
uj5u.com熱心網友回復:
正如您所解釋的,當您的程式啟動時,相關檔案尚不存在。
從QFileSystemWatcher的檔案中:
如果路徑存在,則將路徑添加到檔案系統觀察程式。如果該路徑不存在,或者檔案系統觀察程式已對其進行監視,則不會添加該路徑。
解決您的問題有兩個方面:
- 要獲得新創建檔案的通知,請將父目錄(即您希望檔案出現的目錄)添加到您的觀察者(在您的情況下,只需'.')。然后,當創建任何新檔案時,您將收到通知(directoryChanged 信號)。您的
update_graph方法已經為此動態做好了準備,因為它會檢查您的目標檔案是否存在;因此您可以directoryChanged像使用fileChanged. - 一旦檔案在那里,為了獲得檔案未來任何更改的通知,將檔案本身添加到觀察者,就像你已經做的那樣,但這次也要這樣做
update_graph(它可能看起來多余,但請注意,如參考上面的內容,多余地添加檔案不是問題;而且當您在開始時添加路徑時,您會覆寫檔案已經存在的情況)。 - 如果檔案被洗掉,您將再次收到directoryChanged事件。您不需要洗掉已洗掉檔案的路徑。
- 最后,請注意
addPath()回傳 bool 成功。所以你應該檢查程式中的回傳值。
這種行為的原因是,當您呼叫 時addPath(),在該路徑找到的檔案或目錄會直接添加到觀察者(而不是指向它的路徑)。因此,通知僅在檔案(或目錄)的生命周期內有效。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/325565.html
