簡體   English   中英

PyQt5 從主模塊外部實時登錄 QTextedit

[英]PyQt5 realtime logging in QTextedit from outside main module

我花了很長時間才在這里發布我的第一個問題,因為我過去所有問題的所有答案都已經在這里了。 但是我還沒有找到解決這個問題的方法,所以這里我們go:

描述:在我的應用程序中,我想在 QTextEdit 小部件中顯示實時日志記錄信息。 為了讓它工作,我實現了我在這里找到的解決方案。

問題:上面鏈接中的代碼就像一個魅力,只要所有執行的函數都是主要 Window class 的一部分。 但是對於我的應用程序,我需要它在主模塊之外工作。 我希望能夠從外部函數獲取實時日志信息(每行一行)(例如:當“someProcess”function 在另一個模塊中時,請參見下面的代碼)。 當我嘗試這樣做時,一切正常,但它不會像以前那樣顯示每行的日志信息行,而是在外部 function 完成后立即顯示所有行。

我認為這是合乎邏輯的,因為在外部 function 中,外部模塊中的記錄器 object 沒有發出信號。 但我無法用一種簡單(或任何)的方式來完成這一點。

主文件

import sys
import time
import logging
import othermodule as om
from PyQt5.QtCore import QObject, pyqtSignal, QThread
from PyQt5.QtWidgets import QWidget, QTextEdit, QPushButton, QVBoxLayout, QApplication

logger = logging.getLogger(__name__)


class ConsoleWindowLogHandler(logging.Handler, QObject):
    sigLog = pyqtSignal(str)
    def __init__(self):
        logging.Handler.__init__(self)
        QObject.__init__(self)

    def emit(self, logRecord):
        message = str(logRecord.getMessage())
        self.sigLog.emit(message)


class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        # Layout
        textBox = QTextEdit()
        textBox.setReadOnly(True)
        self.button = QPushButton('Click')
        vertLayout = QVBoxLayout()
        vertLayout.addWidget(textBox)
        vertLayout.addWidget(self.button)
        self.setLayout(vertLayout)

        # Connect button
        
        self.button.clicked.connect(self.buttonPressed)

        # Thread
        self.bee = Worker(self.test, ())
        self.bee.finished.connect(self.restoreUi)
        self.bee.terminate()

        # Console handler
        consoleHandler = ConsoleWindowLogHandler()
        consoleHandler.sigLog.connect(textBox.append)
        logger.addHandler(consoleHandler)

    def buttonPressed(self):
        self.button.setEnabled(False)
        self.bee.start()

    def restoreUi(self):
        self.button.setEnabled(True)

    def test(self):
        logger.error('Starting')
        om.someProcess()

class Worker(QThread):
    def __init__(self, func, args):
        super(Worker, self).__init__()
        self.func = func
        self.args = args

    def run(self):
        self.func(*self.args)


def main():
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

其他模塊.py

import time
import logging

logger = logging.getLogger(__name__)

def someProcess(self):
    logger.error("starting")
    for i in range(10):
        logger.error("line%d" % i)  # Every iteration, I want to display this line per line 
                                    # in the textbox on the main window
        time.sleep(2)    # in my own code, here comes a time consuming task 

錯誤是因為 ConsoleWindowLogHandler 只處理 main.py 中創建的 logger 的信息,而不處理 othermodule.py 中創建的 logger 的信息,解決方法是指定 ConsoleWindowLogHandler 也是 othermodule.py 中創建的 logger 的處理程序:

# Console handler
consoleHandler = ConsoleWindowLogHandler()
consoleHandler.sigLog.connect(textBox.append)
logger.addHandler(consoleHandler)
om.logger.addHandler(consoleHandler)

注意:雖然這很簡單,但您應該將def someProcess(self):更改為def someProcess():

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM