나는 QStandardItemModel
으로 설정 한 QTableView
입니다. 사용자가보기의 일부 색인에서 데이터를 편집하면 모델에서 dataChanged()
신호를 내 보냅니다. SLOT에서 신호를 처리 할 때 QModelIndex
범위의 사용자가 변경되어 사용자가 입력 한 새 값을 가져올 수 있습니다. 그 시점에서 어떻게 이전 값을 얻을 수 있습니까?QAbstractItemModel :: dataChanged() 신호를 처리 할 때 이전 값을 얻는 방법?
답변
QStandardItemModel
은 간단한 모델이므로이 기능이있는 신호가 없습니다. 이러한 기능을 원할 경우 QAbstractItemModel
의 하위 클래스를 만들고 사용자 정의 클래스를 사용하여 setData
을 구현하고 이전 값과 새 값을 모두 포함하는 사용자 정의 신호를 내보낼 수 있습니다.
해결 방법으로 일부 슬롯 QStandardItemModel
의 itemChanged
신호를 연결할 수 있습니다
connect(model,SIGNAL(itemChanged(QStandardItem*)),this, SLOT(onModelChanged(QStandardItem*)));
, 이전의 값으로 사용하는 모델의 Qt::UserRole
로 새로운 값을 저장 슬롯은 다음에 호출 할 때 :
void MyClass::onModelChanged(QStandardItem *item)
{
disconnect(model,SIGNAL(itemChanged(QStandardItem*)),this, SLOT(onModelChanged(QStandardItem*)));
QVariant oldValue = item->data(Qt::UserRole);
item->setData(item->data(Qt::DisplayRole), Qt::UserRole); //Store the new value for next use
connect(model,SIGNAL(itemChanged(QStandardItem*)),this, SLOT(onModelChanged(QStandardItem*)));
}
사용자 대리인 그래서 가능한 솔루션과 데이터를 변경하는 단계이다
#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을 사용했지만 원하는 경우 이전 구문을 사용할 수 있습니다.
일부 연구 끝에 나는이 동작을 달성 할 표준 방법이 없다는 것을 알아 냈습니다. 이 문제를 해결하기 위해 나는 QStandardItemModel
을 상속 같은 setData()
다시 구현했다 :
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
...
}
모든 솔루션이 전에 :
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()
신호를 처리하는 슬롯에있는 기존 데이터에 액세스 할 수 있습니다
setData()
중 수정할 때이 값을 유지하고 수정할 수 있습니다.
slot'a 인수에 언급 된 색인에 이전 값이 아닌 새로운 값이 포함되어 있는지 실제로 확인 했습니까? – vahancho
예. 이것이 신호가 "dataBeforeChange"가 아닌 dataChanged()라고하는 이유입니다. –
글쎄, 데이터가 이미 변경된 경우, 이전 데이터가 필요한 것은 무엇입니까? – vahancho