如何在Qt应用程序中实时显示HTML个文件
How to display HTML file in Qt application in realtime
我正在使用 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
在每次使用 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
注意:我在问题中post编辑的代码在QRunnable
的run()
函数中作为好吧,但我没有 post 它是为了让它更容易理解。现在我正在 post 整合它,因为我认为完整的代码可能对某人有帮助。
如您所见,我利用了 readlines()
的一个特性:在第一次调用后,它从它读取的 最后一行 开始读取。这意味着如果你调用这个函数一次,第二次调用 readlines()
(保持文件打开)并且文件没有改变,你会得到一个空列表;而如果文件发生更改,您将获得一个仅包含新行而不是所有文件行的列表。
classDatalogStreamer
的一个对象在主class中创建并在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
的方法(class DatalogEdit
,它只不过是 QTextEdit
的子 class)。
这是该方法的实现:
def update_datalog(self, lines):
self.moveCursor(QTextCursor.End)
for line in lines:
self.insertHtml(line.replace("\t", " ") + "<br>")
self.verticalScrollBar().setValue(self.verticalScrollBar().maximum())
我使用 insertHtml()
因为 行(字符串列表)可以包含 html 标签。此外,我用 4 个空格 (* ) 替换了“\t”,因为它被忽略了,并在每一行之后添加了一个换行符 (
*).
通过这个简单的解决方案,我解决了三个问题:
- 没有打印相同的后续行(只是第一行),而现在它们都被打印了
QTextEdit
中的文本现在被格式化为 HTML 文件中的文本
- 从文件读取“采样时间”从 未定义(非常小的时间)增加到 0.1 秒,减少了计算量
我正在使用 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
在每次使用 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
注意:我在问题中post编辑的代码在QRunnable
的run()
函数中作为好吧,但我没有 post 它是为了让它更容易理解。现在我正在 post 整合它,因为我认为完整的代码可能对某人有帮助。
如您所见,我利用了 readlines()
的一个特性:在第一次调用后,它从它读取的 最后一行 开始读取。这意味着如果你调用这个函数一次,第二次调用 readlines()
(保持文件打开)并且文件没有改变,你会得到一个空列表;而如果文件发生更改,您将获得一个仅包含新行而不是所有文件行的列表。
classDatalogStreamer
的一个对象在主class中创建并在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
的方法(class DatalogEdit
,它只不过是 QTextEdit
的子 class)。
这是该方法的实现:
def update_datalog(self, lines):
self.moveCursor(QTextCursor.End)
for line in lines:
self.insertHtml(line.replace("\t", " ") + "<br>")
self.verticalScrollBar().setValue(self.verticalScrollBar().maximum())
我使用 insertHtml()
因为 行(字符串列表)可以包含 html 标签。此外,我用 4 个空格 (* ) 替换了“\t”,因为它被忽略了,并在每一行之后添加了一个换行符 (
*).
通过这个简单的解决方案,我解决了三个问题:
- 没有打印相同的后续行(只是第一行),而现在它们都被打印了
QTextEdit
中的文本现在被格式化为 HTML 文件中的文本- 从文件读取“采样时间”从 未定义(非常小的时间)增加到 0.1 秒,减少了计算量