当委托失去焦点时,取消在 QTableView 中的编辑
Cancel edit in QTableView when delegate loses focus
我正在使用基本的QTableView + QAbstractTableModel架构。数据可以通过 QAbstractItemDelegate 子类进行编辑。一切都按预期工作,但我需要稍微改变编辑行为:
Qt 默认行为为:
- 对于打开的委托编辑器,按 Enter 确认编辑
- 对于打开的委托编辑器,点击 Esc 会取消编辑
- 对于打开的委托编辑器,单击其他表视图单元格可确认编辑
我想摆脱最后一个。如果委托编辑器失去焦点,则应取消编辑(即,它不应发出 editorDone()),以便用户只能通过按 Enter 来提交更改。
有没有方便的方法可以做到这一点?
提前致谢
我在应用程序中遇到了同样的问题,这是我的解决方案:
深入研究QAbstractItemDelegate的源代码(通过查找commitData
),您可以找到一个私有函数editorEventFilter(QObject *object, QEvent *event)
,它具有以下代码(简化):
if (event->type() == QEvent::KeyPress) {
// just handling Esc/Enter/Return key strokes...
} else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
// ok it's now handling focus related events
if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
QWidget *w = QApplication::focusWidget();
// lines omitted: checking focus is in editor or editor's child
if (tryFixup(editor))
emit q->commitData(editor); // <- here
}
} // else if (...) {...}
这是tryFixup
函数:
bool QAbstractItemDelegatePrivate::tryFixup(QWidget *editor)
{
if (QLineEdit *e = qobject_cast<QLineEdit*>(editor)) {
if (!e->hasAcceptableInput()) {
// fix input using validator.fixup()
// if QLineEdit has a QValidator
return e->hasAcceptableInput();
}
}
return true;
}
因此,在大多数情况下,QAbstractItemDelegate 会在编辑器失去焦点时提交编辑器的数据。为了防止这种行为,我们可以覆盖eventFilter
并过滤掉QFocusOutEvent
和QHideEvent
。我正在使用 PySide6 6.5.0,这是代码:
def checkObjectIsEditor(self, obj):
return False # maybe something like isinstance(obj, YourEditorType)
def eventFilter(self, object, event):
if (
self.checkObjectIsEditor(object)
and event.type() in [QEvent.Type.FocusOut, QEvent.Type.Hide]
):
widget = QApplication.focusWidget()
while widget:
if self.checkIsEditor(widget):
return False
widget = widget.parentWidget()
# The focus is neither in editor nor in its child.
# Now close the editor, and not commiting its data.
object.hide()
object.deleteLater()
# or maybe self.destroyEditor(object)
return True # stop the event from propagating
return super().eventFilter(object, event)
希望这能帮助任何有需要的人。
覆盖类,找出最后一个行为是你不想要的函数,然后覆盖该函数并将其实现留空,然后像往常一样调用它,但现在它什么都不做(或者做其他事情,你正在编程让它做任何你想做的事情)
仅在用户与编辑器小部件交互时在编辑器小部件上设置属性,并在修改模型之前检查此属性是否正确设置setModelData()
。
例如,我们有一个 ButtonDelegate,它似乎在聚焦时被触发。我们应用了一个属性来了解setModelData()
何时由点击触发,如下所示:
QWidget * ButtonDelegate::createEditor(QWidget * parent,
QStyleOptionViewItem const &,
QModelIndex const &) const
{
auto editor = new QToolButton(parent);
connect(editor, &QAbstractButton::clicked, this, [=]
{
editor->setProperty("clicked", true);
Q_EMIT const_cast<ButtonDelegate *>(this)->commitData(editor);
});
return editor;
}
void ButtonDelegate::setModelData(QWidget * editor, QAbstractItemModel * model,
QModelIndex const & index) const
{
if (model && index.isValid() && editor->property("clicked") == true)
{
model->setData(index, true, Qt::CheckStateRole);
editor->setProperty("clicked", {}); // Reset to handle next click
}
}
我会覆盖模型中的QAbstractItemModel::setData()
,并在尝试设置与给定项目已经存在的相同数据时跳过发出dataChanged()
。
- QTableView:endMoveRows在模型中重置水平页眉大小
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息
- 将QIcon添加到QTableView单元格
- 编辑文件中的文本
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- SetDlgItemInt 不会更改嵌入资源的编辑框
- 如何在QTableView中排序和更改日期格式
- 我无法在Visual Studio代码中使用CIN输入答案,它说输入您的年龄,但它说只读文本编辑器如何解决这个问题?
- QTableview Search
- C++,Qt:仅在双击后编辑qtablewidget项目
- 编辑字符串以包含括号 c++ 之间的变量
- Arduino函数无法编辑数组
- 调试符号中缺少 QObject 类信息(编辑但存在其他 Qt 类)
- 在qtableView中编辑单元格之后,如何避免使用选项卡键进行编辑模式
- 使用列中的组合框编辑QTableView
- 当委托失去焦点时,取消在 QTableView 中的编辑
- 如何在QTableView中使某列不可编辑,使某列可编辑
- Qt:背景的QtAbstractItemView (QTableView),而编辑一个条目
- 在QTableView中用作编辑器的QComboBox中刷新选项
- QTableView是不可编辑的