我有QTableView
设置了QStandardItemModel
。用户在视图中的某个索引中编辑数据,然后模型发出dataChanged()
信号。在我处理SIGNAL的SLOT中,我有QModelIndex
范围的用户更改,因此我可以获得用户输入的新值。我如何在那时获得旧值?
答案 0 :(得分:2)
由于QStandardItemModel
是一个简单的模型,因此它没有具有此功能的信号。如果您想要这样的功能,您可以继承QAbstractItemModel
并拥有自己的自定义类并实现setData
并发出包含旧值和新值的自定义信号。
作为一种解决方法,您可以将itemChanged
的{{1}}信号连接到某个插槽:
QStandardItemModel
并将新值存储为模型中的connect(model,SIGNAL(itemChanged(QStandardItem*)),this, SLOT(onModelChanged(QStandardItem*)));
,以便在下次调用插槽时将其用作旧值:
Qt::UserRole
答案 1 :(得分:2)
经过一番研究后,我发现没有标准的方法来实现这种行为。要解决这个问题,我必须继承QStandardItemModel
并重新实现setData()
,如下所示:
class RecallModel : public QStandardItemModel
{
public:
RecallModel (QObject * parent = 0) : QStandardItemModel(parent) {}
// Reimplemented
bool setData(const QModelIndex &index, const QVariant &value, int role= Qt::EditRole)
{
// backup the previous model data
if (role == Qt::EditRole || role == Qt::DisplayRole)
QStandardItemModel::setData(index, data(index), Qt::UserRole + 1);
return QStandardItemModel::setData(index, value, role);
}
};
之后,我可以访问处理dataChanged()
信号的插槽中的旧数据:
void SomeObject::handleDataChange(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
...
const QVariant &vOldData = index.data(Qt::UserRole + 1); // here is the old data
const QVariant &vNewData = index.data(Qt::DisplayRole); // here is the new data
...
}
答案 2 :(得分:1)
用户可以使用委托更改数据,因此可能的解决方案是:
#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H
#include <QItemDelegate>
class ItemDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit ItemDelegate(QObject *parent = 0);
protected:
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setEditorData(QWidget * editor, const QModelIndex & index) const;
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const;
void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const;
signals:
void dataChanged(QString oldValue,QString newValue) const;
public slots:
private:
mutable QString old;//we want change member data in const method
};
#endif // ITEMDELEGATE_H
正如您所看到的,默认情况下有很多方法const
,所以我做了一些技巧(例如mutable
)以避免出现问题。同样在我编辑的答案中,我没有将旧数据存储在UserRole+1
中,所有这些都是使用旧mutable
变量完成的。
CPP:
#include "itemdelegate.h"
#include <QLineEdit>
#include <QDebug>
ItemDelegate::ItemDelegate(QObject *parent) :
QItemDelegate(parent)
{
}
QWidget *ItemDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QLineEdit *editor = new QLineEdit(parent);
return editor;
}
void ItemDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
old = index.model()->data(index, Qt::EditRole).toString();//store old data
QLineEdit *line = qobject_cast<QLineEdit*>(editor);
line->setText(old);
}
void ItemDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index)const
{
QLineEdit *line = static_cast<QLineEdit*>(editor);
QString data = line->text();
emit dataChanged(old, line->text());
model->setData(index, data);
}
void ItemDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
用法:
ItemDelegate * del = new ItemDelegate;
connect(del,&ItemDelegate::dataChanged,[=](QString oldValue,QString newValue) {
qDebug() << "old" << oldValue<< "new" <<newValue ;
});
ui->tableView->setItemDelegate(del);
我测试了它并且它有效。它适用于不同的型号。 QTableView
默认使用lineEdit
作为委托,因此用户不会在视图中看到任何更改。
我在这里使用C++11
(CONFIG += c++11
到.pro
文件)和new syntax of signals and slots,但当然如果需要,您可以使用旧语法。
答案 3 :(得分:0)
此答案之前的所有解决方案都依赖于Qt特定的功能。但是你可以在Qt框架之外移动INSERT,UPDATE,DELETE(不是SQL,但是常见的)功能。查看工作单元设计模式,以及&#34;企业应用程序架构模式&#34; 中的相关域对象模式。
您可以修改此模式以保留旧值,并在setData()
期间修改时获取它。