我正在使用QTreeView
和QAbstractItemModel
开发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中是否存在通用的方式,无论它是什么,说“我已完成编辑,获取数据并将其传递给模型”?
答案 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;
}