Cheerio,这里的Qt新手愿意学习...
我当前正在尝试创建一个Qt应用程序,该应用程序从多个logging.Record
实例中打印QThread
个对象。
为此,我提出了一个最低限度的工作示例,包括带有QTextEdit
和QPushButton
的应用程序本身,自定义记录器和需要从单独的线程执行的任意长时间运行的进程。>
该代码实际上可以正常工作!之所以在此发布,是因为我想听听您对如何进行增强的意见。我也希望从您那里得到一些输入,以便为此编写一个稳定的,可以正常工作的小样板。我看到人们经常遇到这个问题。
所以这是代码...
app.py
设置基本的QApplication
并初始化执行QThread
的{{1}}。
LongRunningProcess.run()
logger.py
在我看来,这有点令人费解。对于实例化此Logger的每个调用者,将创建一个import sys
from PySide2 import QtCore, QtGui, QtWidgets
from logger import Logger
from lrp import LongRunningProcess
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.log = Logger(self._log_to_qtextedit)
self.create_gui()
self.thread = QtCore.QThread()
self.worker = LongRunningProcess(self._log_to_qtextedit)
self.thread.started.connect(self.worker.run)
self.worker.moveToThread(self.thread)
self.button.clicked.connect(self.run_process)
def run_process(self):
self.thread.start()
def create_gui(self):
self.centralwidget = QtWidgets.QWidget(self)
layout = QtWidgets.QVBoxLayout(self.centralwidget)
self.textedit = QtWidgets.QTextEdit(self)
# change font of output log to monospaced
font = QtGui.QFont()
font.setFamily("Courier New")
self.textedit.setFont(font)
self.button = QtWidgets.QPushButton("push me")
layout.addWidget(self.textedit)
layout.addWidget(self.button)
self.setLayout(layout)
self.setCentralWidget(self.centralwidget)
self.resize(700, 100)
self.log.info("Gui initialised...")
def on_application_shutdown(self):
self.thread.quit()
@QtCore.Slot(str)
def _log_to_qtextedit(self, msg):
self.textedit.append(msg)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
app.aboutToQuit.connect(window.on_application_shutdown)
window.show()
sys.exit(app.exec_())
并将其传递给Queue
。
QueueHandler
连接到自定义处理程序QueueListener
。每次调用处理程序的QtHandler
方法时,此处理程序都会实例化QObject
以便发出信号。该信号将连接到emit()
传递的log_func
。
我还试图在每个线程之间共享队列,但是导致GUI中没有显示很多记录。
Logger
lrp.py
可以是需要一些时间才能完成的任何事情。
import logging
import sys
from logging.handlers import QueueHandler, QueueListener
from queue import Queue
from PySide2 import QtCore
class SignalEmitter(QtCore.QObject):
request_textedit_update = QtCore.Signal(str)
def __init__(self):
super(SignalEmitter, self).__init__()
class QtHandler(logging.Handler):
def __init__(self):
super(QtHandler, self).__init__()
self.signal_emitter = SignalEmitter()
def emit(self, record):
record = self.format(record)
self.signal_emitter.request_textedit_update.emit(record)
class Logger(logging.Logger):
def __init__(self, log_func, level=logging.DEBUG, name="root"):
super(Logger, self).__init__(name)
queue = Queue()
self.setLevel(level)
self.handlers_ = {
"queue_handler": QueueHandler(queue),
"console_handler": logging.StreamHandler()
}
formatter = logging.Formatter("%(asctime)s %(name)-12s %(levelname)-8s %(message)s")
for handler in self.handlers_.values():
print(handler)
handler.setFormatter(formatter)
self.addHandler(handler)
qthandler = QtHandler()
qthandler.signal_emitter.request_textedit_update.connect(log_func)
qthandler.setFormatter(formatter)
self.listener = QueueListener(
queue, qthandler
)
self.listener.start()
def stop_listening(self):
self.listener.stop()