C++ 如何覆盖QSqlRelationalTableModel?
我想在最后一行中添加一列。 我想在那一栏加上几个按钮。 然而,我不知道怎么做。 关注点如下C++ 如何覆盖QSqlRelationalTableModel?,c++,database,qt,C++,Database,Qt,我想在最后一行中添加一列。 我想在那一栏加上几个按钮。 然而,我不知道怎么做。 关注点如下 当我重写数据(constqmodelindex&index,int-role)时,我必须重写所有数据,这是可以避免的吗 当我将新的QPushButton作为QVariant返回时,它会抛出一条错误消息。我不知道怎么修理。 C:\Qt\5.4\mingw491\u 32\include\QtCore\qvariant.h:462:错误:“qvariant::qvariant(void*)”是私有内联qvar
C:\Qt\5.4\mingw491\u 32\include\QtCore\qvariant.h:462:错误:“qvariant::qvariant(void*)”是私有内联qvariant(void*)Q_DECL_EQ_DELETE代码>
QVariant ActionSqlRelationModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
{
return new QPushButton;
}
return QVariant();
}
void MyModel : public BaseModel {
public:
QVariant data(const QModelIndex & index, int role) const Q_DECL_OVERRIDE {
if (index.column() == BaseModel::columnCount()) {
// extra column
return "MyData";
}
return BaseModel::data(index, role);
}
int columnCount() const Q_DECL_OVERRIDE {
return BaseModel::columnCount() + 1;
}
...
};
您还可以使用qidentityproxymodel
而不是派生基础模型,并替代其方法-这样,您就可以轻松地添加额外的列,无论使用什么模型来保留其余数据
具体而言:
void MyProxy : public QIdentityProxyModel {
public:
QVariant data(const QModelIndex & index, int role) const Q_DECL_OVERRIDE {
if (index.column() == BaseModel::columnCount()) {
// extra column
return "MyData";
}
return QIdentityProxyModel::data(index, role);
}
int columnCount() const Q_DECL_OVERRIDE {
return BaseModel::columnCount() + 1;
}
MyProxy(QObject * parent = 0) : QIdentityProxyModel(parent) {}
};
然后在视图上使用,而不是在原始模型上使用。要让代理知道它应该充当哪个模型的代理,可以使用setSourceModel
方法。例如:
int main(int argc, char ** argv) {
QApplication app(argc, argv);
QTableView view;
QSqlRelationalTableModel model;
MyProxy proxy;
...
proxy.setSourceModel(&model);
view.setModel(&proxy);
view.show();
return app.exec();
}
当我将新的QPushButton作为QVariant返回时,它会抛出一条错误消息
首先,从data
方法返回一个小部件,即使您成功地返回了它,视图也不会处理它。视图不会使用这样的小部件做任何事情-他们会忽略它。所以它不会起作用。我在下面展示一个人如何做,但这只是为了满足你的好奇心——这是一个完全无用的练习。这样的代码“有效”,但它返回的小部件将被忽略
如果要将按钮显示为特定数据项的表示形式,则需要向视图中添加自定义委托。该代理处理具有非标准需求的项目的可视化和小部件。必须重新实现QStyledItemDelegate
(或QAbstractItemDelegate
),并使用setItemDelegateForColumn
在视图的给定列上设置它
为了满足您的好奇心:
QObject
及其派生的类不可复制,因此不能直接存储在QVariant
中。相反,您可以存储指向对象的共享指针:
typedef QSharedPointer<QPushButton> QPushButtonPtr;
Q_DECLARE_METATYPE(QPushButtonPtr)
...
QVariant ActionSqlRelationModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
{
return QPushButtonPtr(new QPushButton);
}
return QSqlRelationModel::data(index, role); // underlying class's data
}
typedef QSharedPointer QPushButtonPtr;
Q_DECLARE_元类型(QPushButtonPtr)
...
QVariant ActionSqlRelationModel::数据(常量QModelIndex和索引,int角色)常量
{
如果(角色==Qt::DisplayRole)
{
返回QPushButtonPtr(新的QPushButton);
}
返回QSqlRelationModel::data(索引,角色);//基础类的数据
}
我不太清楚通过在模型中存储按钮,您想要实现什么。这样做当然没问题,只是没有一个视图知道如何使用您提供给它们的按钮。似乎我应该使用QASstructTableModel和QSqlQuery自己来做……谢谢您的回答。我想你的anwser是我想要的,但我不明白你在说什么。我将尝试了解QidentityProxymodel是如何工作的。还要考虑使用Qptr。@Woody A
QIdentityProxyModel
是一个代理:它将请求转发到源模型,然后您可以以任何合适的方式修改请求。通过从QIdentityProxyModel
派生,您可以使用所需的任何源模型。通过直接从源模型派生,您仅限于该模型,而不限于其他模型。使用共享指针存储小部件是将小部件存储在QVariant
中的唯一方法,但我仍然要问:为什么您希望将小部件存储在QVariant
和模型中?没有任何现有视图可以使用这样的小部件!我希望我可以让一行可以按下或检查。通过按该行,它可以显示一个新的小部件。这就是我想要的。您对QIdentityProxyModel功能的解释很有趣。我无法理解模型代理的含义。@Woody从字典中得知:“代理是授权代表另一个人行事的代理或替代品”。在这里,QIdentityProxyModel
是一个可以用来代替原始模型的模型。该模型将为您访问原始模型-您可以通过调用代理上的setSourceModel
方法来设置它。代理可以在任何类型的模型上使用。@Woody“通过按行,它可以显示一个新的小部件。”不,它不能,因为您不能简单地通过模型的data
方法将小部件传递给视图。当然,您可以这样做,但是视图不知道如何处理它,您将拥有大量不需要的小部件,它们什么都不做。