我最近制作了一个示例来(更)熟悉QStyledItemDelegate
有关单元格的内联编辑:
在这个示例中,我做了底层数据模型重载的更新QStyledItemDelegate::setModelData()
。
在阅读了这个问题之后,我只是测试了如果输入完成(或者严格来说:中止)会发生什么ESC。这是我观察到的:
基础数据保持不变。
深入挖掘(即在我的重载中设置断点setModelData()
),我观察到setModelData()
在这种情况下甚至没有调用。
可能,通过对他的代表进行一点重新设计,可以轻松解决 OPs 问题。
最后,我的派生类(声明)用于实现“全功能”委托来内联编辑表格单元格:
class ValueNameDelegate: public QStyledItemDelegate {
// methods:
public:
/// @name Construction & Destruction
//@{
/// constructor.
ValueNameDelegate();
/// destructor.
virtual ~ValueNameDelegate() = default;
// disabled:
ValueNameDelegate(const ValueNameDelegate&) = delete;
ValueNameDelegate& operator=(const ValueNameDelegate&) = delete;
//@}
protected:
/// @name Overloaded Event Handlers
//@{
// inserts editor in table (by setParent(pQParent)) and
// returns the editor widget to edit cell.
virtual QWidget* createEditor(
QWidget *pQParent, const QStyleOptionViewItem &qOption,
const QModelIndex &qMIndex) const override;
// removes editor from table (by setParent(nullptr)).
virtual void destroyEditor(
QWidget *pQEditor, const QModelIndex &qMIndex) const override;
// reads data from table model and updates editor.
virtual void setEditorData(
QWidget *pQEditor, const QModelIndex &qMIndex) const override;
// reads data from editor and updates table model.
virtual void setModelData(
QWidget *pQEditor, QAbstractItemModel *pQModel,
const QModelIndex &qMIndex) const override;
//@}
};
笔记:
就我而言,事先只创建了一个编辑器小部件。它被重新用于每个单元格编辑(而不是为每个编辑创建一个新的)。
这与Qt Spin Box Delegate Example有点不同,但可以按预期工作。
我无法想象这对 OPs 问题没有任何影响。
根据反馈,OP 希望处理失去焦点的事件,例如中止输入。这与默认情况下的处理方式相反QLineEdit
。
所以,我的解决方案是提供一个重载版本的QLineEdit
. 它没有改变 的行为QLineEdit
,而是简单地跟踪成员bool _confirmed
是否Enter被按下。最棘手的部分是确定另一个合适的事件或信号来重置成员。最后,我决定focusOutEvent()
在正确的时间调用它,因此适合这项任务。
testQLineEdit-Finished.cc
:
#include <QtWidgets>
class LineEdit: public QLineEdit {
private:
// flag: true ... last finished editing was confirmed
bool _confirmed;
public:
// Construction & Destruction
explicit LineEdit(
const QString &contents = QString(), QWidget *pQParent = nullptr):
QLineEdit(contents, pQParent),
_confirmed(false)
{
QObject::connect(this, &QLineEdit::returnPressed,
[this](){ onSigReturnPressed(); });
}
LineEdit(QWidget *pQParent): LineEdit(QString(), pQParent) { }
virtual ~LineEdit() = default;
LineEdit(const LineEdit&) = delete;
LineEdit& operator=(const LineEdit&) = delete;
public:
// returns whether last finished editing was confirmed.
bool isConfirmed() { return _confirmed; }
protected:
virtual void focusOutEvent(QFocusEvent *pQEvent) override
{
_confirmed = false;
QLineEdit::focusOutEvent(pQEvent);
}
private:
void onSigReturnPressed() { _confirmed = true; }
};
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
LineEdit qEdit(QString::fromUtf8("Hello World"));
qEdit.show();
// install signal handlers
QObject::connect(&qEdit, &LineEdit::editingFinished,
[&]() {
qDebug() << "Edit confirmed:" << qEdit.isConfirmed();
});
// runtime loop
return app.exec();
}
的输出Edit confirmed: true
是通过按 来实现的Enter,false
通过单击来实现。
这做得相当简单,可能做得更复杂。然而,它显示了用相当少的代码行数实现的原理。