QLineEdit如何触发QAbstractItemDelegate::commitData

How does QLineEdit triger QAbstractItemDelegate::commitData

我正在使用 QTreeViewQAbstractItemModel 开发 Qt 应用程序。 该模型包含一些异构数据,需要不同的控件进行编辑。我通过自定义委托来实现它,查询 model.data(Qt::EditRole) 并且模型将 return QWidget 用作编辑器。

我喜欢 QLineEdit 的工作方式 - 当我按下回车键时,delegate::setModelData 会自动调用,所以我 不需要 连接 QLineEdit::editingFinishedQAbstractItemDelegate::setModelData(),这非常方便,因为 QLineEdit 是从模型 returned 作为 QWidget 到委托的,它不必关心它是什么类型的小部件. 使用 QComboBox 有点棘手 - 我希望组合框在做出选择后提交,到目前为止我只能通过 connect(myComboBox, SIGNAL(activated(QString)), myDelegate, commitData())); 来完成 但是,我的代表不知道编辑器小部件的类型,我不想为模型最终传递给它的每个新编辑器编辑代表的代码。当在连接到其 activated() 信号的插槽中单击输入时,我真的很想强制组合框执行与 QLineEdit 相同的操作。

那么,QLineEdit 调用委托的 setModelData 做什么? Qt 中是否有一种通用的编辑方式,无论它是什么 "I'm done editing, take the data and pass it to the model"?

QStyledItemDelegate(和 QItemDelegate)定义了一个事件过滤器,如果您按 Tab 键或 return。

,它会调用 commitData

请参阅 Qt 4.8.6 source 中的以下摘录:

bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event)
{
    QWidget *editor = qobject_cast<QWidget*>(object);
    if (!editor)
        return false;
    if (event->type() == QEvent::KeyPress) {
        switch (static_cast<QKeyEvent *>(event)->key()) {
        case Qt::Key_Tab:
            emit commitData(editor);
            emit closeEditor(editor, QAbstractItemDelegate::EditNextItem);
            return true;
        case Qt::Key_Backtab:
            emit commitData(editor);
            emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem);
            return true;
        case Qt::Key_Enter:
        case Qt::Key_Return:
#ifndef QT_NO_TEXTEDIT
            if (qobject_cast<QTextEdit *>(editor) || qobject_cast<QPlainTextEdit *>(editor))
                return false; // don't filter enter key events for QTextEdit
            // We want the editor to be able to process the key press
            // before committing the data (e.g. so it can do
            // validation/fixup of the input).
#endif // QT_NO_TEXTEDIT
#ifndef QT_NO_LINEEDIT
            if (QLineEdit *e = qobject_cast<QLineEdit*>(editor))
                if (!e->hasAcceptableInput())
                    return false;
#endif // QT_NO_LINEEDIT
            QMetaObject::invokeMethod(this, "_q_commitDataAndCloseEditor",
                                      Qt::QueuedConnection, Q_ARG(QWidget*, editor));
            return false;
        case Qt::Key_Escape:
            // don't commit data
            emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache);
            break;
        default:
            return false;
        }
        if (editor->parentWidget())
            editor->parentWidget()->setFocus();
        return true;
    } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
        //the Hide event will take care of he editors that are in fact complete dialogs
        if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
            QWidget *w = QApplication::focusWidget();
            while (w) { // don't worry about focus changes internally in the editor
                if (w == editor)
                    return false;
                w = w->parentWidget();
            }
#ifndef QT_NO_DRAGANDDROP
            // The window may lose focus during an drag operation.
            // i.e when dragging involves the taskbar on Windows.
            if (QDragManager::self() && QDragManager::self()->object != 0)
                return false;
#endif

            emit commitData(editor);
            emit closeEditor(editor, NoHint);
        }
    } else if (event->type() == QEvent::ShortcutOverride) {
        if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
            event->accept();
            return true;
        }
    }
    return false;
}