gpt4 book ai didi

python - 文件更改时 QFileSystemModel 不更新

转载 作者:行者123 更新时间:2023-11-30 22:24:20 29 4
gpt4 key购买 nike

我遇到 QFileSystemModel 无法显示文件更改的问题。当文件第一次创建时,它会立即显示出来。但是当文件本身发生变化时,大小和时间戳不会更新。我已经多次尝试强制模型更新,但没有真正成功。我所取得的最好成绩就是完全替换该模型。尽管这会导致此错误:

QSortFilterProxyModel: index from wrong model passed to mapToSource

下面的测试代码创建一个空目录的 TableView 。单击左侧按钮会创建一个文件 (foo.txt)。连续单击将数据附加到文件。据我了解,QFileSystemModel 不需要刷新,但第二个按钮是我的尝试。

任何有关我做错的事情的帮助将不胜感激!

# Testing with python3.6.3 and pip installed pyqt5 5.9.2 in virtualenv on Ubuntu
import os, sys, tempfile
from PyQt5 import QtCore, QtWidgets


class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)

layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
self._view = QtWidgets.QTableView()
layout.addWidget(self._view)

self._modify_button = QtWidgets.QPushButton('Create')
layout.addWidget(self._modify_button)
self._refresh_button = QtWidgets.QPushButton('Refresh')
layout.addWidget(self._refresh_button)

self._modify_button.clicked.connect(self._modify)
self._refresh_button.clicked.connect(self._refresh)

self._model, self._proxy = None, None
self.temp_dir = tempfile.TemporaryDirectory(dir=os.path.dirname(os.path.abspath(__file__)))
self.init_model(self.temp_dir.name)

def init_model(self, path):
self._model = QtWidgets.QFileSystemModel()
self._model.setFilter(QtCore.QDir.AllDirs | QtCore.QDir.AllEntries)

self._proxy = QtCore.QSortFilterProxyModel(self)
self._proxy.setSourceModel(self._model)
self._view.setModel(self._proxy)
# self._view.setModel(self._model)

self._model.directoryLoaded.connect(self._loaded)
self._model.setRootPath(path)

def _loaded(self):
path = self._model.rootPath()
source_index = self._model.index(path)
index = self._proxy.mapFromSource(source_index)
self._view.setRootIndex(index)
# self._view.setRootIndex(source_index)

def _modify(self):
"""Create or modify foo.txt..model should see and update"""
self._modify_button.setText('Modify')
file_name = os.path.join(self.temp_dir.name, 'foo.txt')
with open(file_name, 'a') as txt_file:
print('foo', file=txt_file)

# def _refresh(self):
# # This only seems to work once..and its a flawed approach since it requires permission to write
# temp = tempfile.NamedTemporaryFile(dir=self.temp_dir.name)

# def _refresh(self):
# self._model.beginResetModel()
# self._model.endResetModel()

# def _refresh(self):
# self._proxy.setFilterRegExp('foo')
# self._proxy.setFilterRegExp(None)
# self._proxy.invalidate()
# self._proxy.invalidateFilter()
# self._proxy.reset()
#
# root_index = self._model.index(self._model.rootPath())
# rows = self._model.rowCount(root_index)
# proxy_root_index = self._proxy.mapFromSource(root_index)
# topLeft = self._proxy.index(0, 0, proxy_root_index)
# bottomRight = self._proxy.index(rows - 1, self._model.columnCount(proxy_root_index) - 1, proxy_root_index)
# # self._proxy.dataChanged.emit(topLeft, bottomRight)
# self._model.dataChanged.emit(topLeft, bottomRight)

# def _refresh(self):
# # This only seems to work once
# self._model.setRootPath('')
# self._model.setRootPath(self.temp_dir.name)

def _refresh(self):
# This seems heavy handed..but seems to work
# ..though generates "QSortFilterProxyModel: index from wrong model passed to mapToSource" spam in console
self.init_model(self.temp_dir.name)


if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = Widget()
widget.show()
sys.exit(app.exec_())

最佳答案

更新:

从 Qt-5.9.4 开始,QT_FILESYSTEMMODEL_WATCH_FILES 环境变量可用于打开每个文件的监视(请参阅 QTBUG-46684 )。在模型开始缓存有关文件的信息之前,需要将其设置为非空值一次。但请注意,这会将文件观察器添加到遇到的每个文件,因此这可能会使其成为 expensive solution on some systems .

下面留下原始答案作为问题的解释。

<小时/>

此问题是由长期存在的 Qt bug 引起的:QTBUG-2276 。不幸的是,目前看来它不太可能很快得到修复。正如错误报告评论中所示,问题的核心似乎是这样的:

It's an OS limitation. A change to a file does not mean the directory is modified.

唯一真正的解决方法是将QFileSystemWatcher附加到每个文件,这显然可以是prohibitively expensive (无论如何,在某些平台上)。

除了这个问题之外,QFileSystemModel类当前不提供用于强制刷新的 API,并且正如您所发现的,似乎没有任何可靠的解决方法。 SO 和其他地方提供的大多数“解决方案”都提出了一些变体:

root = fsmodel.rootPath()
fsmodel.setRootPath('')
fsmodel.setRootPath(root)

但如您所知,这似乎只能工作一次 - 可能是由于当前实现文件信息缓存的方式存在一些怪癖。

目前看来强制更新的唯一方法是替换整个模型。可以通过重构 init_model 方法来防止当前实现产生的错误消息,如下所示:

def init_model(self, path):
if self._proxy is None:
self._proxy = QtCore.QSortFilterProxyModel(self)
else:
# remove the current source model
self._proxy.setSourceModel(None)
self._model = QtWidgets.QFileSystemModel()
self._model.setFilter(QtCore.QDir.AllDirs | QtCore.QDir.AllEntries)
self._proxy.setSourceModel(self._model)
self._view.setModel(self._proxy)
self._model.directoryLoaded.connect(self._loaded)
self._model.setRootPath(path)

这是一个非常令人不满意的情况,但目前似乎没有任何明显的解决方法。

关于python - 文件更改时 QFileSystemModel 不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47851152/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com