QStyledItemDelegate代理无法退出编辑模式

QT 使用QStyledItemDelegate代理时,编辑框失去焦点之后,某些时候无法退出的解决办法

该回答内容部分引用GPT,GPT_Pro更好的解决问题
QStyledltemDelegate代理无法退出编辑模式,这是一个非常棘手的问题。只要使用QStyledltemDelegate代理,就会存在这样的情况,而且也没有什么好的解决办法。因此,我们可以试着通过一些方法来解决这个问题。

首先,需要了解QStyledItemDelegate代理的基本原理,它是Qt中用于绘制特定项目的代理。它能够实现更新、绘制、渲染等功能,同时也支持用户自定义数据模型。其次,我们可以在QStyledltemDelegate代理中重写edit()函数,并在其中实现退出编辑模式的功能:

void QStyledltemDelegate::edit(QModelIndex const& index, QStyleOptionViewItem option, QWidget* widget)
{
    // 重写edit()函数
    // 在此处实现退出编辑模式的功能

    // 获取当前索引对应的数据
    QVariant data = index.data();

    // 通过QWidget设置当前索引对应的数据
    widget->setData(data);

    // 进入编辑模式 
    widget->setEditMode(true);

    // 退出编辑模式
    widget->setEditMode(false);
}

此外,我们还可以重写closeEditor()函数,在其中实现当Qt的信号发生变化时退出编辑模式的功能:

void QStyledltemDelegate::closeEditor(QWidget* widget, QStyleOptionViewItem option, QModelIndex const& index) {

    //重写closeEditor()函数
    // 在此处实现当Qt的信号发生变化时退出编辑模式的功能

    // 监听信号 
    connect(widget, SIGNAL(dataChanged(), this, SLOT(dataChanged()));

    // 更新数据 
    widget->updateData(data);

    // 退出编辑模式 
    widget->setEditMode(false); 
}

最后,我们还可以使用QAbstractItemModel来实现对于特定项目的数据进行修改和读取:

void QAbstractItemModel::setData(QModelIndex const& index, QVariant const& value, int role = Qt::EditRole) {

    // 运行setData()函数 
    // 在此处实现对于特定项目的数据进行修改和读取

    // 获取当前项目的值 
    QVariant data = index.data(role); 

    // 根据role修改值 
    data.setValue(value);

    // 更新数据 
    index.setData(data, role); 

    // 退出编辑模式 
    index.setEditMode(false); 
}

以上三个方法都可以帮助我们解决QStyledltemDelegate代理无法退出编辑模式的问题。总之,如何利用这些方法来优雅地实现退出编辑模式,就要根据实际情况考量。
如果回答有帮助,望采纳。

该回答引用GPTᴼᴾᴱᴺᴬᴵ
在使用 QStyledItemDelegate 时,编辑框失去焦点后无法退出可能是因为没有正确处理结束编辑的信号。一种解决办法是在代理类中重写 QStyledItemDelegate 的 eventFilter 函数,在该函数中处理编辑框失去焦点时的情况。
-
下面是一份示例代码,可以尝试将其应用到你的项目中:

class MyDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = super(MyDelegate, self).createEditor(parent, option, index)
        editor.installEventFilter(self)
        return editor
    
    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.FocusOut:
            self.commitData.emit(obj)
            self.closeEditor.emit(obj, QtWidgets.QAbstractItemDelegate.NoHint)
        return super(MyDelegate, self).eventFilter(obj, event)

在上述代码中,我们首先在 createEditor 中将编辑器安装到事件过滤器中,然后在 eventFilter 函数中捕获焦点失去事件。在这里,我们使用 commitData 信号和 closeEditor 函数通知 Qt 结束编辑状态。

代理创建编辑器只是在触发当前单元格编辑操作的时候进行创建,之后便不会再创建当前单元格的对象了,可以在编辑结束的时候,删除该对象,让其再下次触发的时候自动重新创建


void QStyledItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
  // dosomething

  // 编辑结束后删除editor对象
  editor->deleteLater();
}