PyQt QFileDialog - 多目录选择
PyQt QFileDialog - Multiple Directory Selection
我正在尝试创建一个允许用户 select 多个目录的 QFileDialog。
经过讨论 here and the faq here,但我不确定我做错了什么。我得到一个文件对话框,但它仍然只允许我 select 一个目录(文件夹)。
这是在 Windows 7
代码:
class FileDialog(QtGui.QFileDialog):
def __init__(self, *args):
QtGui.QFileDialog.__init__(self, *args)
self.setOption(self.DontUseNativeDialog, True)
self.setFileMode(self.DirectoryOnly)
self.tree = self.findChild(QtGui.QTreeView)
self.tree.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
self.list = self.findChild(QtGui.QListView)
self.list.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
ex = FileDialog()
ex.show()
sys.exit(app.exec_())
编辑:
所以在尝试了更多之后,如果我在文件对话框中 select "Detail View",multiselection 就可以工作了。但是,如果我 select "List View" 它不起作用。知道为什么吗?
FAQ 中的示例代码并不健壮,因为它假设对话框只有一个 QListView
和一个 QTreeView
。当有多个直接子对象时,findChild
的行为是不确定的:所以它曾经起作用可能只是纯粹的运气。
一个更强大的解决方案是在其模型类型为 QFileSystemModel
:
的任何视图上重置选择模式
for view in self.findChildren((QListView, QTreeView)):
if isinstance(view.model(), QFileSystemModel):
view.setSelectionMode(QAbstractItemView.ExtendedSelection)
这是一个简单的演示脚本:
from PyQt5 import QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.button = QtWidgets.QPushButton('Choose Directories')
self.button.clicked.connect(self.handleChooseDirectories)
self.listWidget = QtWidgets.QListWidget()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.listWidget)
layout.addWidget(self.button)
def handleChooseDirectories(self):
dialog = QtWidgets.QFileDialog(self)
dialog.setWindowTitle('Choose Directories')
dialog.setOption(QtWidgets.QFileDialog.DontUseNativeDialog, True)
dialog.setFileMode(QtWidgets.QFileDialog.DirectoryOnly)
for view in dialog.findChildren(
(QtWidgets.QListView, QtWidgets.QTreeView)):
if isinstance(view.model(), QtWidgets.QFileSystemModel):
view.setSelectionMode(
QtWidgets.QAbstractItemView.ExtendedSelection)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
self.listWidget.clear()
self.listWidget.addItems(dialog.selectedFiles())
dialog.deleteLater()
if __name__ == '__main__':
app = QtWidgets.QApplication(['Test'])
window = Window()
window.show()
app.exec_()
我正在尝试创建一个允许用户 select 多个目录的 QFileDialog。
经过讨论 here and the faq here,但我不确定我做错了什么。我得到一个文件对话框,但它仍然只允许我 select 一个目录(文件夹)。
这是在 Windows 7
代码:
class FileDialog(QtGui.QFileDialog):
def __init__(self, *args):
QtGui.QFileDialog.__init__(self, *args)
self.setOption(self.DontUseNativeDialog, True)
self.setFileMode(self.DirectoryOnly)
self.tree = self.findChild(QtGui.QTreeView)
self.tree.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
self.list = self.findChild(QtGui.QListView)
self.list.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
ex = FileDialog()
ex.show()
sys.exit(app.exec_())
编辑:
所以在尝试了更多之后,如果我在文件对话框中 select "Detail View",multiselection 就可以工作了。但是,如果我 select "List View" 它不起作用。知道为什么吗?
FAQ 中的示例代码并不健壮,因为它假设对话框只有一个 QListView
和一个 QTreeView
。当有多个直接子对象时,findChild
的行为是不确定的:所以它曾经起作用可能只是纯粹的运气。
一个更强大的解决方案是在其模型类型为 QFileSystemModel
:
for view in self.findChildren((QListView, QTreeView)):
if isinstance(view.model(), QFileSystemModel):
view.setSelectionMode(QAbstractItemView.ExtendedSelection)
这是一个简单的演示脚本:
from PyQt5 import QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.button = QtWidgets.QPushButton('Choose Directories')
self.button.clicked.connect(self.handleChooseDirectories)
self.listWidget = QtWidgets.QListWidget()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.listWidget)
layout.addWidget(self.button)
def handleChooseDirectories(self):
dialog = QtWidgets.QFileDialog(self)
dialog.setWindowTitle('Choose Directories')
dialog.setOption(QtWidgets.QFileDialog.DontUseNativeDialog, True)
dialog.setFileMode(QtWidgets.QFileDialog.DirectoryOnly)
for view in dialog.findChildren(
(QtWidgets.QListView, QtWidgets.QTreeView)):
if isinstance(view.model(), QtWidgets.QFileSystemModel):
view.setSelectionMode(
QtWidgets.QAbstractItemView.ExtendedSelection)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
self.listWidget.clear()
self.listWidget.addItems(dialog.selectedFiles())
dialog.deleteLater()
if __name__ == '__main__':
app = QtWidgets.QApplication(['Test'])
window = Window()
window.show()
app.exec_()