首先,这个问题类似于另一个问题https://ci.appveyor.com/project/LudovicRousseau/pyscard,主要区别在于,在这种情况下,每次我的某个文件更新时,我都不想替换整个模型。
在现实世界的例子中,我的应用程序将打开几个文件,所以我基本上只是想了解如何更新一个特定QFileSystemModel项目的信息(大小,修改日期),下面你有一点点可以玩有,正如你在代码中看到的那样,我已经无意中尝试使用QFileSystemModel not updating when files change:
import sys
import os
from PyQt5.Qt import * # noqa
class DirectoryTreeWidget(QTreeView):
def __init__(self, path=QDir.currentPath(), *args, **kwargs):
super().__init__(*args, **kwargs)
self.init_model(path)
self.expandsOnDoubleClick = False
self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
self.setAutoScroll(True)
def init_model(self, path):
self.extensions = ["*.*"]
self.path = path
model = QFileSystemModel(self)
model.setRootPath(QDir.rootPath())
model.setReadOnly(False)
model.setFilter(QDir.AllDirs | QDir.NoDot | QDir.AllEntries)
self.setModel(model)
self.set_path(path)
def set_path(self, path):
self.path = path
model = self.model()
index = model.index(str(self.path))
if os.path.isfile(path):
self.setRootIndex(model.index(
os.path.dirname(str(self.path))))
self.scrollTo(index)
self.setCurrentIndex(index)
else:
self.setRootIndex(index)
class Foo(QWidget):
def __init__(self, path):
super().__init__()
self.path = path
self.tree_view = DirectoryTreeWidget(path=".")
self.tree_view.show()
bt = QPushButton(f"Update {path}")
bt.pressed.connect(self.update_file)
layout = QVBoxLayout()
layout.addWidget(self.tree_view)
layout.addWidget(bt)
self.setLayout(layout)
# New file will automatically refresh QFileSystemModel
self.create_file()
def create_file(self):
with open(self.path, "w") as f:
data = "This new file contains xx bytes"
f.write(data.replace("xx", str(len(data))))
def update_file(self):
model = self.tree_view.model()
# Updating a file won't refresh QFileSystemModel, the question is,
# how can we update that particular item to be refreshed?
data = "The file updated is much larger, it contains xx bytes"
with open(self.path, "w") as f:
f.write(data.replace("xx", str(len(data))))
# file_info = self.obj.model.fileInfo(index)
# file_info.refresh()
index = model.index(self.path)
model.setData(index, model.data(index))
QMessageBox.about(None, "Info", f"{self.path} updated, new size is {len(data)}")
def main():
app = QApplication(sys.argv)
foo = Foo("foo.txt")
foo.setMinimumSize(640, 480)
foo.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
所以问题是,我怎样才能实现update_file
更新该特定文件foo.txt
的信息?
目标是更新那个文件而不用像setData那样替换整个模型,一旦该模型项被更新,项目就不会在视图中排序/移动。< / p>
答案 0 :(得分:1)
Qt v5.9.4引入了环境变量import sys
import os
from PyQt5.Qt import * # noqa
class DirectoryTreeWidget(QTreeView):
def __init__(self, path=QDir.currentPath(), *args, **kwargs):
super().__init__(*args, **kwargs)
self.init_model(path)
self.expandsOnDoubleClick = False
self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
self.setAutoScroll(True)
def init_model(self, path):
os.environ["QT_FILESYSTEMMODEL_WATCH_FILES"] = '1'
self.extensions = ["*.*"]
self.path = path
model = QFileSystemModel(self)
model.setRootPath(QDir.rootPath())
model.setReadOnly(False)
model.setFilter(QDir.AllDirs | QDir.NoDot | QDir.AllEntries)
self.setModel(model)
self.set_path(path)
def set_path(self, path):
self.path = path
model = self.model()
index = model.index(str(self.path))
if os.path.isfile(path):
self.setRootIndex(model.index(
os.path.dirname(str(self.path))))
self.scrollTo(index)
self.setCurrentIndex(index)
else:
self.setRootIndex(index)
class Foo(QWidget):
def __init__(self, path):
super().__init__()
self.path = path
self.tree_view = DirectoryTreeWidget(path=".")
self.tree_view.show()
bt = QPushButton(f"Update {path}")
bt.pressed.connect(self.update_file)
layout = QVBoxLayout()
layout.addWidget(self.tree_view)
layout.addWidget(bt)
self.setLayout(layout)
self.create_file()
def create_file(self):
with open(self.path, "w") as f:
data = "This new file contains xx bytes"
f.write(data.replace("xx", str(len(data))))
def update_file(self):
model = self.tree_view.model()
data = "The file updated is much larger, it contains xx bytes"
with open(self.path, "w") as f:
f.write(data.replace("xx", str(len(data))))
index = model.index(self.path)
model.setData(index, model.data(index))
QMessageBox.about(None, "Info", f"{self.path} updated, new size is {len(data)}")
def main():
app = QApplication(sys.argv)
foo = Foo("foo.txt")
foo.setMinimumSize(640, 480)
foo.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
以便解决QTBUG-46684,您可以在changelog中详细了解它:
QTBUG-46684现在可以启用每个文件观看了 设置环境变量QT_FILESYSTEMMODEL_WATCH_FILES, 允许跟踪文件大小的变化。
因此,为了使示例正常工作,您可以将envar设置为非空值,即:
{{1}}
几点意见: