QFileDialog 作为 TableView 的编辑器失去焦点时关闭

3 投票
1 回答
712 浏览
提问于 2025-04-18 01:17

我有一个 QTableView,它关联了一个 QAbstractTableModel,这个模型里有一些列是目录名称。我想用 QFileDialog 作为编辑器来修改这些列的内容。这有点特别,因为编辑器不会放在表格单元格里(因为空间不够)。

我用 QStyledItemDelegate 基本上实现了这个功能:

class DirectorySelectionDelegate(QStyledItemDelegate):

    def createEditor(self, parent, option, index):        
        editor = QFileDialog(parent)
        editor.setFileMode(QFileDialog.Directory)       
        editor.resize(400, 400)
        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())

当我双击单元格时,会弹出一个 QFileDialog,我可以选择想要的目录,点击选择后,它会在模型中更新这个值。

不过,如果因为某种原因 QFileDialog 失去焦点,它就会关闭,数据会恢复成原来的值。我希望对话框能一直保持打开状态,直到用户点击取消或选择,但我找不到实现这个的方法。

附加问题:不知为什么,这个对话框会忽略 resize() 的调用,启动时非常小(这让失去焦点的情况更容易发生)。我该如何改变对话框的大小呢?

1 个回答

4

这是正常的行为。

标准视图并不是小部件的容器,每个单元格都是在需要的时候才绘制出来的。用于编辑的小部件只有在触发编辑时才会被创建,并且会覆盖在视图上。然后会调用代理来创建合适的编辑小部件,并将单元格的位置和大小作为参数传入。

视图会保留编辑器小部件的所有权,因为一旦失去焦点,你显然就无法再进行编辑,所以视图会删除这个编辑器。

如果你在setModelData函数中没有返回任何东西,模型就不会被更新。说模型被恢复到原始数据是不正确的,因为它根本没有被改变过。

我建议你尝试将QFileDialog设置为模态打开(editor.setModal(true)),这样对话框必须关闭后,焦点才能转移到其他小部件上。

撰写回答