I am trying to make an app that monitors hardware, I would like to use Qthreadpool instead of having a thread for each widget and I am having trouble connecting signals to display the output. I am also getting no errors.
My old code runs fine and displays what it should using QThread:
import sys
from PyQt4 import QtCore, QtGuiimport ui
import time
import mem_stats
class MainClass(QtGui.QMainWindow, ui.Ui_MainWindow):
def __init__(self, parent= None):
super(MainClass, self).__init__(parent)
self.setupUi(self)
self.mem_worker = MemWorker()
self.mem_worker.start()
self.connect(self.mem_worker, QtCore.SIGNAL('MEM_STATS'),self.show_mem_stats)
def show_mem_stats(self, free_mem):
self.free_memory_lcd.display(free_mem)
class MemWorker(QtCore.QThread):
def __init__(self):
super(MemWorker, self).__init__()
def run(self):
while True:
free_mem = mem_stats.free_mem()
self.emit(QtCore.SIGNAL('MEM_STATS'), free_mem)
time.sleep(1)
if __name__ == '__main__':
a = QtGui.QApplication(sys.argv)
app = MainClass()
app.show()
sys.exit(a.exec_())
But when i change MemWorker class to QRunnable the code runs with no errors but the QlcdNumber doesn't display anyting.
Here's my new code:
import sys
from PyQt4 import QtCore, QtGui
import ui
import time
import mem_stats
class WorkerSignals(QtCore.QObject):
mem_signal = QtCore.pyqtSignal(int)
class MainClass(QtGui.QMainWindow, ui.Ui_MainWindow):
def __init__(self, parent= None):
super(MainClass, self).__init__(parent)
self.setupUi(self)
self.mem_worker = MemWorker()
self.thread_pool = QtCore.QThreadPool()
self.thread_pool.setMaxThreadCount(2)
self.connect(self.mem_worker.signal, QtCore.SIGNAL('MEM_STATS'), self.show_mem_stats)
def show_mem_stats(self, free_mem):
self.free_memory_lcd.display(free_mem)
self.thread_pool.start(self.mem_worker)
class MemWorker(QtCore.QRunnable):
def __init__(self):
super(MemWorker, self).__init__()
self.signal = WorkerSignals()
def run(self):
while True:
free_mem = mem_stats.free_mem()
self.signal.mem_signal.emit(QtCore.SIGNAL('MEM_STATS'), free_mem)
time.sleep(1)
if __name__ == '__main__':
a = QtGui.QApplication(sys.argv)
app = MainClass()
app.show()
sys.exit(a.exec_())
The problem is that you are not starting the QRunnable
, you want to start it in the slot and it will never be called if the QRunnable
is not started. On the other hand, it is currently recommended to use the new connection syntax, and finally it is recommended to use the @pyqtSlot decorator
that makes the connection from the C++ side, making it faster with fewer resources.
from PyQt4 import QtCore, QtGui
import ui
import time
import mem_stats
class WorkerSignals(QtCore.QObject):
mem_signal = QtCore.pyqtSignal(int)
class MainClass(QtGui.QMainWindow, ui.Ui_MainWindow):
def __init__(self, parent= None):
super(MainClass, self).__init__(parent)
self.setupUi(self)
self.mem_worker = MemWorker()
self.thread_pool = QtCore.QThreadPool()
self.thread_pool.setMaxThreadCount(2)
self.mem_worker.signal.mem_signal.connect(self.show_mem_stats)
self.thread_pool.start(self.mem_worker)
@QtCore.pyqtSlot(int)
def show_mem_stats(self, free_mem):
self.free_memory_lcd.display(free_mem)
class MemWorker(QtCore.QRunnable):
def __init__(self):
super(MemWorker, self).__init__()
self.signal = WorkerSignals()
def run(self):
while True:
ree_mem = mem_stats.free_mem()
self.signal.mem_signal.emit(free_mem)
time.sleep(1)
if __name__ == '__main__':
import sys
a = QtGui.QApplication(sys.argv)
app = MainClass()
app.show()
sys.exit(a.exec_())