QFileDialog作为TableView的编辑器:如何获取结果?

1 投票
1 回答
748 浏览
提问于 2025-04-18 01:23

我在一个 QTableView 中使用 QFileDialog 来编辑某些列。这基本上是可以工作的(虽然有一些焦点问题,具体可以看 这里):

class DirectorySelectionDelegate(QStyledItemDelegate):    
    def createEditor(self, parent, option, index):
        editor = QFileDialog(parent)
        editor.setFileMode(QFileDialog.Directory)       
        editor.setModal(True)
        return editor    

    def setEditorData(self, editor, index):
        val = index.model().data(index, Qt.DisplayRole)
        fs = val.rsplit(os.path.sep, 1)
        if len(fs) == 2:
            bdir, vdir = fs
        else:
            bdir = "."
            vdir = fs[0]

        editor.setDirectory(bdir)        
        editor.selectFile(vdir)        

    def setModelData(self, editor, model, index):
        model.setData(index, editor.selectedFiles()[0])   

    def updateEditorGeometry(self, editor, option, index):
        r = option.rect
        r.setHeight(600)
        r.setWidth(600)            
        editor.setGeometry(r)

但是,当编辑器关闭时,我找不到方法来区分是点击了 选择 还是 取消(或者是失去焦点),因为 setEditorData 函数在所有情况下都会被调用。我也看不到如何从 QFileDialog 中获取作为 editor 的结果,所有我能找到的例子都使用了 exec_ 的返回值,而我没有办法访问这个值。

1 个回答

2

setModelData 这个地方,你可以在设置模型数据之前,先检查一下编辑器的 结果。默认情况下,结果是 QDialog.Rejected,这只有在用户真的选择了一个文件时才会改变。

    def setModelData(self, editor, model, index):
        if editor.result() == QtGui.QDialog.Accepted:
            model.setData(index, editor.selectedFiles()[0])   

更新

经过一些后续测试,很明显无论文件对话框是怎么运行的(即使是用 exec),在代理编辑器的上下文中,它的 result 永远不会被正确重置。所以我们需要一点间接的方法。根据 QFileDialog.filesSelected 的文档,这个信号只会在对话框被接受时发送(即使没有选择任何文件)。所以我们可以利用这个机制来强制得到正确的对话框结果,像这样:

class DirectorySelectionDelegate(QtGui.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = QtGui.QFileDialog(parent)
        editor.filesSelected.connect(
            lambda: editor.setResult(QtGui.QDialog.Accepted))
        ...

    def setModelData(self, editor, model, index):
        print(editor.result())
        if editor.result() == QtGui.QDialog.Accepted:
            model.setData(index, editor.selectedFiles()[0])

撰写回答