python - 具有代理模型按日期排序的 QFileDialog 实际上使用日期的字母顺序
问题描述
在 PyQt 5.11.2(在 Windows 10 上)中,设置了 DontUseNativeDialog 选项的 QFileDialog 在按“修改日期”列排序时存在错误:它不按实际日期排序 - 它按非零填充 MM 的字母顺序排序-DD-YYYY 字符串,表示 9-12-2018 显示为比 12-12-2018 更新。 有解决方法或修复方法吗?
本机对话框确实按日期正确排序,但是,使用非本机对话框的动机是本机对话框不尊重 fileDialog.setProxyModel (用于通过更复杂的正则表达式规则过滤掉某些文件),描述here和here,我认为文档中的这一行已详细说明/暗示了这一点:
默认情况下,如果平台有一个平台原生文件对话框,则将使用它。在这种情况下,用于构造对话框的小部件将不会被实例化,因此相关的访问器(例如 layout() 和 itemDelegate() 将返回 null。您可以设置 DontUseNativeDialog 选项以确保将使用基于小部件的实现而不是本机对话框。
代码:通过调用 self.load() 生成对话框(无参数)
def load(self,fileName=None):
if not fileName:
fileDialog=QFileDialog()
fileDialog.setOption(QFileDialog.DontUseNativeDialog)
fileDialog.setProxyModel(CSVFileSortFilterProxyModel(self))
fileDialog.setNameFilter("CSV Radio Log Data Files (*.csv)")
fileDialog.setDirectory(self.firstWorkingDir)
if fileDialog.exec_():
fileName=fileDialog.selectedFiles()[0]
...以及只有一个功能的整个 CSVFileSortFilterProxyModel 类:
# code for CSVFileSortFilterProxyModel partially taken from
# https://github.com/ZhuangLab/storm-control/blob/master/steve/qtRegexFileDialog.py
class CSVFileSortFilterProxyModel(QSortFilterProxyModel):
def __init__(self,parent=None):
# print("initializing CSVFileSortFilterProxyModel")
super(CSVFileSortFilterProxyModel,self).__init__(parent)
# filterAcceptsRow - return True if row should be included in the model, False otherwise
#
# do not list files named *_fleetsync.csv or *_clueLog.csv
# do a case-insensitive comparison just in case
def filterAcceptsRow(self,source_row,source_parent):
# print("CSV filterAcceptsRow called")
source_model=self.sourceModel()
index0=source_model.index(source_row,0,source_parent)
# Always show directories
if source_model.isDir(index0):
return True
# filter files
filename=source_model.fileName(index0).lower()
# filename=self.sourceModel().index(row,0,parent).data().lower()
# print("testing lowercased filename:"+filename)
# never show non- .csv files
if filename.count(".csv")<1:
return False
if filename.count("_fleetsync.csv")+filename.count("_cluelog.csv")==0:
return True
else:
return False
解决方案
问题是由自定义 QSortFilterProxyModel 引起的,因为在 lessThan 方法中,值是字符串,解决方案是转换为适当的类型进行比较:
class CSVFileSortFilterProxyModel(QtCore.QSortFilterProxyModel):
def filterAcceptsRow(self,source_row,source_parent):
source_model = self.sourceModel()
index0=source_model.index(source_row,0,source_parent)
if source_model.isDir(index0):
return True
filename = source_model.fileName(index0).lower()
if filename.count(".csv")<1:
return False
return filename.count("_fleetsync.csv")+filename.count("_cluelog.csv") == 0
def lessThan(self, left, right):
source_model = self.sourceModel()
if left.column() == right.column() == 1:
if source_model.isDir(left) and not source_model.isDir(right):
return True
return source_model.size(left) < source_model.size(right)
if left.column() == right.column() == 2:
return source_model.type(left) < source_model.type(right)
if left.column() == right.column() == 3:
return source_model.lastModified(left) < source_model.lastModified(right)
return super(CSVFileSortFilterProxyModel, self).lessThan(left, right)
正如@ekhumoro所指出的,一个更简单的选择是覆盖代理排序:
class CSVFileSortFilterProxyModel(QtCore.QSortFilterProxyModel):
def filterAcceptsRow(self,source_row,source_parent):
source_model = self.sourceModel()
index0=source_model.index(source_row,0,source_parent)
if source_model.isDir(index0):
return True
filename = source_model.fileName(index0).lower()
if filename.count(".csv")<1:
return False
return filename.count("_fleetsync.csv")+filename.count("_cluelog.csv") == 0
def sort(self, column, order):
self.sourceModel().sort(column, order)
推荐阅读
- python - 运行后如何清理tox环境?
- ios - 如何在 Xcode 构建成功或错误时播放声音?
- java - 带有自定义适配器的列表视图不显示所有项目
- php - 从 SQL DB 中提取数据,保存在浏览器中并在单独的页面上显示为值
- python - Matplot lib 错误“AttributeError:‘AxesSubplot’对象没有属性‘get’”
- asp.net-mvc - 在 ASP.NET MVC 应用程序中安装 Bootstrap
- c++ - C ++如何修复错误“对非常量的引用的初始值必须是左值”?
- php - 子部分未将样式注入其父刀片布局
- androidx - 如何在 androidX 中添加 CardView
- python-3.x - GridSearchCV 似乎没有评估我为其提供的所有参数