QLineEdit如何分解QAbstractItemDelegate :: commitData

时间:2015-05-05 20:58:07

标签: qt delegates qlineedit qabstractitemmodel

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

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

那么,activated()做什么来调用委托QLineEdit? 在编辑器的Qt中是否存在通用的方式,无论它是什么,说“我已完成编辑,获取数据并将其传递给模型”?

1 个答案:

答案 0 :(得分:2)

QStyledItemDelegate(和QItemDelegate)定义了一个事件过滤器,如果您按Tab键或返回,则会调用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;
}