Python QTreeView/QFileSystemModel-比较文件和;显色
我有两个QFileSystemModel附加的QTreeview。一个是本地目录,另一个指向服务器 我期待着改变文件上的文本颜色的基础上,其关系到相反的位置。例如: 如果服务器和本地都有相同的修改时间-设置为绿色 如果服务器是最新的-将本地设置为红色,服务器设置为橙色。等等 我有过多个这样的工作示例,但我总是遇到同样的障碍,用户界面反应迟钝。我在两个QFileSystemModels中都使用了data()函数来实现这一点,我尝试在data()之外执行线程操作以返回颜色,但这只会使我的所有文件都变成灯光显示。基于我移动鼠标,文件将随机变为绿色/红色/橙色 我目前有一个date modified列作为一个解决方案,但它不能帮助用户知道他们是否已经从本地服务器获得了一个文件 有没有人能在没有UI chug的情况下完成类似的工作?或者甚至找到一个方法从线程返回结果,并让它为正确的条目工作 我理解这可能看起来有点混乱,但这里是我初始化根的地方(其中一些全局变量在其他地方使用)Python QTreeView/QFileSystemModel-比较文件和;显色,python,pyside,pyside2,Python,Pyside,Pyside2,我有两个QFileSystemModel附加的QTreeview。一个是本地目录,另一个指向服务器 我期待着改变文件上的文本颜色的基础上,其关系到相反的位置。例如: 如果服务器和本地都有相同的修改时间-设置为绿色 如果服务器是最新的-将本地设置为红色,服务器设置为橙色。等等 我有过多个这样的工作示例,但我总是遇到同样的障碍,用户界面反应迟钝。我在两个QFileSystemModels中都使用了data()函数来实现这一点,我尝试在data()之外执行线程操作以返回颜色,但这只会使我的所有文件都变
def initroot(self,loc):
'''
此函数用于设置服务器和本地服务器的起始目录
不处理除顶层以外的任何事情
'''
全局本地掩码
全局服务器掩码
全局服务器根
全局用户根
全局gserver模型
全局GlocalModel
如果loc==“服务器”:
self.serverRoot=self.cb\u serverWorkspace.currentText()
serverRoot=self.serverRoot
self.serverModel=ServerFileSystemModel()
GserverModel=self.serverModel
self.tv_serverFiles.setModel(self.serverModel)
#self.serverModel.setRootPath(QtCore.QDir.rootPath())
self.serverModel.setRootPath(“”)
self.tv_serverFiles.setRootIndex(self.serverModel.index(self.serverRoot))
self.tv_serverFiles.setUniformRowHeights(True)
self.tv_serverFiles.setExpandsOnDoubleClick(True)
self.tv\u serverFiles.hideColumn(1)
self.tv\u serverFiles.hideColumn(2)
self.tv_serverFiles.setColumnWidth(0400)
如果loc==“本地”:
self.userRoot=self.cb\u localWorkspace.currentText()
userRoot=self.userRoot
self.localModel=LocalFileSystemModel()
GlocalModel=self.localModel
self.tv\u localFiles.setModel(self.localModel)
#self.localModel.setRootPath(QtCore.QDir.rootPath())
self.localModel.setRootPath(“”)
self.tv_localFiles.setRootIndex(self.localModel.index(self.userRoot))
self.tv_serverFiles.setUniformRowHeights(True)
self.tv\u localFiles.setExpandsOnDoubleClick(True)
self.tv\u localFiles.hideColumn(1)
self.tv\u localFiles.hideColumn(2)
self.tv_localFiles.setColumnWidth(0400)
然后,我的两个QFileSystemModels几乎就是这样(这是我的非线程示例)
类服务器文件系统模型(qtwidts.QFileSystemModel):
定义初始化(self,*args,**kwargs):
super(ServerFileSystemModel,self)。\uuuu init\uuuu(*args,**kwargs)
def数据(self,index,role=QtCore.Qt.DisplayRole):
尝试:
全局GlocalModel
全局gserver模型
serverPath=self.filePath(索引)
localMask=userRoot+“/”
serverMask=serverRoot+“/”
newPath=serverPath.replace(serverMask,localMask)
serverIndex=GserverModel.index(serverPath)
localIndex=GlocalModel.index(新路径)
如果role==QtCore.Qt.TextColorRole和serverPath.endswith(“.fbx”)以及os.path.exists(newPath)存在,并且下载==False:
如果GlocalModel.lastModified(localIndex)=GserverModel.lastModified(serverIndex):
返回QtGui.QColor(#58cd1c)
如果GlocalModel.lastModified(localIndex)GserverModel.lastModified(serverIndex):
返回QtGui.QColor(#ed1111)
返回super(ServerFileSystemModel,self).data(索引,角色)
除:
返回super(ServerFileSystemModel,self).data(索引,角色)
还有什么事就告诉我
编辑******
我被要求放置最小的可复制代码,所以我们开始吧
主窗口
class WorkspacerUI(QMainWindow, Ui_MainWindow):
def __init__(self, parent = None):
super(WorkspacerUI, self).__init__(parent)
self.setupUi(self)
self.userRoot = "D:/OCooke_Workspace"
self.serverRoot = "D:/OCooke_Server"
self.initRoots("Local")
self.initRoots("Server")
def initRoots(self, loc):
'''
This function sets the starting directories for both server and local
Does not handle anything except top level
'''
if loc == "Server":
self.serverModel = ServerFileSystemModel()
self.tv_serverFiles.setModel(self.serverModel)
#self.serverModel.setRootPath(QtCore.QDir.rootPath())
self.serverModel.setRootPath("")
self.tv_serverFiles.setRootIndex(self.serverModel.index(self.serverRoot))
self.tv_serverFiles.setUniformRowHeights(True)
self.tv_serverFiles.setExpandsOnDoubleClick(True)
self.tv_serverFiles.hideColumn(1)
self.tv_serverFiles.hideColumn(2)
self.tv_serverFiles.setColumnWidth(0,400)
if loc == "Local":
self.localModel = LocalFileSystemModel()
self.tv_localFiles.setModel(self.localModel)
#self.localModel.setRootPath(QtCore.QDir.rootPath())
self.localModel.setRootPath("")
self.tv_localFiles.setRootIndex(self.localModel.index(self.userRoot))
self.tv_serverFiles.setUniformRowHeights(True)
self.tv_localFiles.setExpandsOnDoubleClick(True)
self.tv_localFiles.hideColumn(1)
self.tv_localFiles.hideColumn(2)
self.tv_localFiles.setColumnWidth(0,400)
q无法与信号一起命名
class WorkerSignals(QObject):
finished = Signal()
result = Signal(object)
progress = Signal(int)
class ColourWorker(QRunnable):
'''
Worker thread
Inherits from QRunnable to handler worker thread setup, signals and wrap-up.
:param callback: The function callback to run on this worker thread. Supplied args and
kwargs will be passed through to the runner.
:type callback: function
:param args: Arguments to pass to the callback function
:param kwargs: Keywords to pass to the callback function
'''
def __init__(self, fn, *args, **kwargs):
super(ColourWorker, self).__init__()
# Store constructor arguments (re-used for processing)
self.fn = fn
self.args = args
self.kwargs = kwargs
self.signals = WorkerSignals()
# Add the callback to our kwargs
self.kwargs['progress_callback'] = self.signals.progress
self.kwargs['indexy']
@Slot()
def run(self):
'''
Initialise the runner function with passed args, kwargs.
'''
# Retrieve args/kwargs here; and fire processing using them
try:
result = self.fn(*self.args, **self.kwargs)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result) # Return the result of the processing
finally:
self.signals.finished.emit() # Done
class ServerFileSystemModel(QFileSystemModel):
def __init__(self, *args, **kwargs):
super(ServerFileSystemModel, self).__init__(*args, **kwargs)
self.threadpool = QThreadPool()
self.colour = None
def data(self, index, role=Qt.DisplayRole):
if role == Qt.TextColorRole:
worker = ColourWorker(self.execute_this_fn, indexy = index) # Any other args, kwargs are passed to the run function
worker.signals.result.connect(self.print_output)
worker.signals.finished.connect(self.thread_complete)
# Execute
self.threadpool.start(worker)
return self.colour
return super(ServerFileSystemModel, self).data(index, role)
#
def execute_this_fn(self, progress_callback, indexy):
serverPath = self.filePath(indexy)
localMask = "D:/OCooke_Workspace/"
serverMask = "D:/OCooke_Server/"
#create an expected path to the local using the server address
# D:/OCooke_Server/2020/file1 turns into D:/OCooke_Workspace/2020/file1
newPath = serverPath.replace(serverMask, localMask)
#Check the stat time between the two locations
if os.stat(newPath).st_mtime == os.stat(serverPath).st_mtime:
return QColor("#58cd1c")
if os.stat(newPath).st_mtime < os.stat(serverPath).st_mtime:
return QColor("#ed7011")
if os.stat(newPath).st_mtime > os.stat(serverPath).st_mtime:
return QColor("#ed1111")
else:
return None
def print_output(self, s):
#return the value of color
self.colour = s
def thread_complete(self):
#ive tried passing the color once the thread completes, no joy
pass
class LocalFileSystemModel(QFileSystemModel):
def __init__(self, *args, **kwargs):
super(LocalFileSystemModel, self).__init__(*args, **kwargs)
def data(self, index, role=Qt.DisplayRole):
return super(LocalFileSystemModel, self).data(index, role)
最后是两个QSystemFileModels
class WorkerSignals(QObject):
finished = Signal()
result = Signal(object)
progress = Signal(int)
class ColourWorker(QRunnable):
'''
Worker thread
Inherits from QRunnable to handler worker thread setup, signals and wrap-up.
:param callback: The function callback to run on this worker thread. Supplied args and
kwargs will be passed through to the runner.
:type callback: function
:param args: Arguments to pass to the callback function
:param kwargs: Keywords to pass to the callback function
'''
def __init__(self, fn, *args, **kwargs):
super(ColourWorker, self).__init__()
# Store constructor arguments (re-used for processing)
self.fn = fn
self.args = args
self.kwargs = kwargs
self.signals = WorkerSignals()
# Add the callback to our kwargs
self.kwargs['progress_callback'] = self.signals.progress
self.kwargs['indexy']
@Slot()
def run(self):
'''
Initialise the runner function with passed args, kwargs.
'''
# Retrieve args/kwargs here; and fire processing using them
try:
result = self.fn(*self.args, **self.kwargs)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result) # Return the result of the processing
finally:
self.signals.finished.emit() # Done
class ServerFileSystemModel(QFileSystemModel):
def __init__(self, *args, **kwargs):
super(ServerFileSystemModel, self).__init__(*args, **kwargs)
self.threadpool = QThreadPool()
self.colour = None
def data(self, index, role=Qt.DisplayRole):
if role == Qt.TextColorRole:
worker = ColourWorker(self.execute_this_fn, indexy = index) # Any other args, kwargs are passed to the run function
worker.signals.result.connect(self.print_output)
worker.signals.finished.connect(self.thread_complete)
# Execute
self.threadpool.start(worker)
return self.colour
return super(ServerFileSystemModel, self).data(index, role)
#
def execute_this_fn(self, progress_callback, indexy):
serverPath = self.filePath(indexy)
localMask = "D:/OCooke_Workspace/"
serverMask = "D:/OCooke_Server/"
#create an expected path to the local using the server address
# D:/OCooke_Server/2020/file1 turns into D:/OCooke_Workspace/2020/file1
newPath = serverPath.replace(serverMask, localMask)
#Check the stat time between the two locations
if os.stat(newPath).st_mtime == os.stat(serverPath).st_mtime:
return QColor("#58cd1c")
if os.stat(newPath).st_mtime < os.stat(serverPath).st_mtime:
return QColor("#ed7011")
if os.stat(newPath).st_mtime > os.stat(serverPath).st_mtime:
return QColor("#ed1111")
else:
return None
def print_output(self, s):
#return the value of color
self.colour = s
def thread_complete(self):
#ive tried passing the color once the thread completes, no joy
pass
class LocalFileSystemModel(QFileSystemModel):
def __init__(self, *args, **kwargs):
super(LocalFileSystemModel, self).__init__(*args, **kwargs)
def data(self, index, role=Qt.DisplayRole):
return super(LocalFileSystemModel, self).data(index, role)
请提供一个示例并改进缩进您的示例远不是最小的,也不是可复制的,但这不是主要问题:模型的
data()
函数应该立即返回,这意味着不应该有阻塞(或线程相关)函数,这是因为项目视图可能会调用data()
每秒数百或数千次,即使是将鼠标悬停在项目上,甚至是相同的项目。坦白地说,我认为您的系统对于您的需求来说太复杂了,我建议您重新考虑整个概念,因为您正在使用(可能)相同结构的固定路径。