【问题标题】:How to display HTML file in Qt application in realtime如何在 Qt 应用程序中实时显示 HTML 文件
【发布时间】:2020-11-17 14:40:59
【问题描述】:

我正在使用 PySide2 开发一个应用程序,我需要显示一个 HTML 文件的内容,该文件是一种日志文件,因此它在不断变化。我需要在我的应用程序上实时查看这些更改。 有没有一种聪明而快速的方法来做到这一点?目前我不断地从文件中读取并比较最后几行以查看是否有新行:如果有,我将其附加到 QTextEdit 小部件。

我认为也许 Qt 提供了一些功能以更智能的方式实现这一目标。

代码片段

    path = some_file.html

    with open(path) as file:
        old = file.readlines()
        try:
            last_line = old[-1]
        except IndexError:
            last_line = ''
        while streaming:
            line = file.readline()
            if line and line != last_line:
                qtext_edit.append(line)
                last_line = line

【问题讨论】:

  • QFileSystemWatcher 可用于监视文件/文件夹的更改。这有帮助吗?
  • @JarMan 您的意思是每次文件更改时都调用 qtext_edit.setHtml(path) 吗?
  • 我只是建议将一个文本行与前一个文本行进行比较不一定是了解文件中是否有新数据的最佳方法。当内容发生变化时,QFileSystemWatcher 可以通过信号通知您。但是,如果它要求您重新加载整个文件,那听起来并不理想。对此我不确定。只是提供想法。
  • @JarMan 我明白了。不幸的是,每次有一个新行时,我都必须添加一个新行。我只是在寻找一种在浏览器中显示 HTML 文件并保持更新的方法。无论如何,您的建议可能有助于减少对 line = file.readline() 的调用以及随后的 if 条件。谢谢
  • 您可以使用QTextStreamQFileSystemWatcher 的组合(@JarMan 评论)。例如,请参阅this answer。您可以使用如下条件:如果文件在nMinutes 中没有更改,则中断外循环。几个月后我的需求出现并尝试时,我会回复。

标签: python html qt real-time pyside2


【解决方案1】:

经过一番挖掘,我得出了一个适合我需要的解决方案。

正如 cmets 中所建议的,最好的方法是利用 QFileSystemWatcher 在每次使用 fileChanged 信号更改文件时触发信号。就我而言,问题是fileChanged 信号没有像我预期的那样连续触发(文件正在被连续写入),因此QTextEdit 没有像我预期的那样更新。

因此可能的最佳解决方案已被丢弃。

我决定重新访问我的旧功能并尝试对其进行优化。 代码如下:

DATALOG_UPDATE_TIME = 0.1

class DatalogSignals(QObject):
    output = Signal(list)


class DatalogStreamer(QRunnable):
    def __init__(self, streaming: bool, datalog: str):
        super().__init__()
        self.streaming = streaming
        self.datalog = datalog
        self.signals = DatalogSignals()

    def run(self):
        with open(self.datalog) as file:
            file.readlines()
            while self.streaming:
                time.sleep(DATALOG_UPDATE_TIME)
                lines = file.readlines()
                if lines:
                    self.signals.output.emit(lines)
        LOG.debug('Datalog streaming finished')

    def stop(self):
        self.streaming = False

注意:我在问题中发布的代码也在QRunnablerun() 函数中,但为了便于理解,我没有发布它。现在我将其完整地发布,因为我认为完整的代码可能对某人有所帮助。

如你所见,我利用了readlines() 的一个特性:在第一次调用之后,它从它读取的最后一行开始读取。这意味着如果你调用这个函数一次,第二次调用readlines()(保持文件打开)并且文件没有改变,你会得到一个空列表;而如果文件发生更改,您将获得一个仅包含新行而不是所有文件行的列表。

DatalogStreamer 类的对象在主类中创建并在QThreadPool 中启动(为了不执行主线程中的代码,因此不阻塞 GUI)。这是开始流式传输的方法:

def _start_datalog_streaming(self):
    self.datalog_streamer = DatalogStreamer(not self.actionDisable.isChecked(), self.datalog_path)
    self.datalog_streamer.signals.output.connect(self.datalog_editor.update_datalog)
    self.thread_pool.start(self.datalog_streamer)

如您所见,output 信号(发出新行的信号)连接到对象datalog_editor(类DatalogEdit,它只是QTextEdit 的子类)的方法。 这是该方法的实现:

def update_datalog(self, lines):
    self.moveCursor(QTextCursor.End)
    for line in lines:
        self.insertHtml(line.replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;") + "<br>")
    self.verticalScrollBar().setValue(self.verticalScrollBar().maximum())

我使用了insertHtml(),因为lines(字符串列表)可以包含html 标签。此外,我将“\t”替换为 4 个空格 (*),因为它被忽略了,并在每行之后添加了一个换行符 (
*)。

通过这个简单的解决方案,我解决了三个问题:

  • 没有打印相同的后续行(只是第一行),而现在它们都被打印了
  • QTextEdit 中的文本现在被格式化为 HTML 文件中的文本
  • 从文件“采样时间”读取从 undefined(非常短的时间)增加到 0.1 秒,从而减少计算工作量

【讨论】:

    猜你喜欢
    • 2013-07-15
    • 1970-01-01
    • 2010-10-23
    • 2011-05-15
    • 2012-12-09
    • 2015-08-30
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    相关资源
    最近更新 更多