我想制作一个QTreeView,显示我用sqlalchemy获得的一些数据。有大约1000-10.000行显示。我认为使用模型比使用更简单的QTreeWidget更好用,因为我认为将模型连接到sqlalchemy相对容易,因为我认为这是经常做的事情。显然它不是......我无法找到这方面的好例子。
我查看了QStandardItemModel的文档,据我了解,我必须为每个值创建一个QStandardItem。有数千行乘以9列,我认为这将非常慢 之前我曾在wxpython中使用过ObjectListView,并希望Qt中的树视图能够起作用,所以当我发现它的复杂程度时,你可以想象我的失望:P。
所以我的问题:
正如你所看到的,我对模型和视图(以及Qt)都是新手,所以任何答案,解释,链接,有用的暗示或者对此有什么看法都非常受欢迎!
答案 0 :(得分:2)
好消息 - 你不需要创建任何QStandardItems。 Qt视图类从不调用数据类上的任何方法,因此您可以以任何您想要的方式存储数据。它们只调用模型类上的方法(不像Ruby on Rails,其中每个数据类都被认为是模型,在Qt中,“model”指的是整个数据类集合。)
我建议继承QAbstractItemModel(参见“Subclassing”部分)并从那里开始工作。如果你只有一个平面列表,你甚至可以设置它,以便你的自定义模型只包装从数据库返回的结果。
我是用C ++做的 - 花了我很长一段时间来绕过它,但是一旦我这样做,它就很容易使用了。这是我的只读模型的基本代码 - 你必须将它翻译成python,但希望它能让你痛苦不堪!
注意:以下代码假设您的数据是一个平面列表(没有父子关系)。如果情况并非如此,请查看this tutorial,了解您必须进行哪些调整的详细信息。
template <typename T> class ListModel : public QAbstractItemModel
{
protected:
//This is where I store my data - it's just a generic list!
//Try using your SQL result instead?
QList<T*> mData;
public:
ListModel(): mData() {}
int columnCount(const QModelIndex& index) const
{
//You'll probably want a different number here:
return 1;
}
QVariant data(const QModelIndex& index, int role) const
{
if(index.isValid() && role == Qt::DisplayRole && index.column() == 0)
{
if(T* t = (T*) index.internalPointer())
{
//Something, based on column number:
return t->data[index.column()];
}
}
return QVariant();
}
QVariant headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0)
{
//Something, based on column number:
return "header text";
}
return QVariant();
}
QModelIndex index(int row, int column, const QModelIndex& parent) const
{
//Tweak this if you have a hierarchical model:
return (parent.isValid())? QModelIndex() : createIndex(row, column, (void*) mData[row]);
}
QModelIndex parent(const QModelIndex& child) const
{
//Tweak this if you have a hierarchical model:
return QModelIndex();
}
int rowCount(const QModelIndex& index) const
{
//Tweak this if you have a hierarchical model:
return (index.isValid())? 0 : mData.count();
}
};