我已经阅读了一堆QThread教程和SO Answers。但是我无法使线程工作。大多数情况下,它只运行一次或打印错误消息。如果我在应用程序启动后立即启动线程,则可以使用线程,但是我希望线程在某些功能后运行,因为我想先设置目录位置。
文件结构如下:
App.py
Controllers/
main_controller.py
recorder.py
Model/
model.py
Views/
main_view.py
App.py
import sys
from PyQt5.QtWidgets import QApplication
from Model.model import Model
from Controllers.main_controller import MainController
from Views.main_view import MainView
class App(QApplication):
def __init__(self, sys_argv):
super().__init__(sys_argv)
self.model = Model()
self.main_controller = MainController(self.model)
self.main_view = MainView(self.model, self.main_controller)
if __name__ == "__main__":
app = App(sys.argv)
sys.exit(app.exec_())
model.py
from PyQt5.QtCore import QObject
class Model(QObject):
def __init__(self):
super().__init__()
self.directory = ""
def get_directory(self):
return self.directory
def set_directory(self, directory):
self.directory = directory
main_view.py
from PyQt5.QtWidgets import QMenu, QSystemTrayIcon, QMainWindow, QFileDialog
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication
from Controllers.recorder import Recorder
class MainView(QMainWindow):
def __init__(self, model, main_controller):
super().__init__()
self._model = model
self._main_controller = main_controller
# UI
icon = QtGui.QIcon("icon24x24.png")
menu = QMenu()
start_action = menu.addAction("Start Recording")
stop_action = menu.addAction("Stop Recording")
self.tray = QSystemTrayIcon()
self.tray.setIcon(icon)
self.tray.setContextMenu(menu)
self.tray.show()
start_action.triggered.connect(self.start_app)
stop_action.triggered.connect(self.stop_app)
self.recordThread = Recorder()
def start_app(self):
directory = QFileDialog.getExistingDirectory(self, "Select Directory")
self._main_controller.set_directory(directory)
self.start_thread()
def start_thread(self):
self.recordThread.start()
def stop_app(self):
self.recordThread.terminate()
QApplication.instance().quit()
print("app stopped")
main_controller.py
from PyQt5.QtCore import QObject
class MainController(QObject):
def __init__(self, model):
super().__init__()
self._model = model
def set_directory(self, directory):
self._model.set_directory(directory)
recorder.py
import time
from PyQt5.QtCore import QThread, QTimer, pyqtSignal
from Model.model import Model
class Recorder(QThread):
job_done = pyqtSignal()
def __init__(self):
QThread.__init__(self)
self._model = Model()
def __del__(self):
self.wait()
def run(self):
while True:
print("I am the loop")
print(self._model.get_directory())
# time.sleep(4 - time.time() % 4)
QThread.sleep(4)
print("now is {}".format(time.time()))
self.job_done.emit()
根据各种教程,我尝试使用各种样式,包括Qthread,QObject,pyqtsignal。但对我没有任何作用。它要么只是打印“我就是循环”,然后退出。或打印
I am the loop
Fatal Python error: could not acquire lock for <_io.BufferedWriter name='<stdout>'> at interpreter shutdown, possibly due to daemon threads
Thread 0x00007f5d1bfff700 (most recent call first):
File "/App/Controllers/recorder.py", line 20 in run
Current thread 0x00007f5d3458f700 (most recent call first):
Aborted
谢谢
答案 0 :(得分:0)
您的代码没有问题。该应用是在调用QFileDialog.getExistingDirectory
之后立即关闭的,因为这是Qt的本质。
关闭所有Windows后,Qt退出
该应用已关闭,因为您不再有任何窗口。您的应用没有QSystemTrayIcon()
窗口。将setQuitOnLastWindowClosed()
设置为False即可解决问题。
yourApp.setQuitOnLastWindowClosed(False)