给定填充 ro QList 的 Qt 模型视图

Posted

技术标签:

【中文标题】给定填充 ro QList 的 Qt 模型视图【英文标题】:Qt Model View for a given populated ro QList 【发布时间】:2010-08-03 16:11:49 【问题描述】:

我得到了一个xyz(代码是int,只是一个例子)的上帝给定的列表,粘在QList(大到可以移动到任何地方)。如何为此创建模型视图?我已经阅读了 Qt 文档,它告诉我,我必须重新实现 dataindexparentrowCountcolumnCount 函数。但是预处理器/编译器需要更多重新实现的功能吗?我已经阅读了我的 Qt Book 中的一章,但它也没有帮助。这是我破解的代码:

class XModel : public QAbstractListModel

Q_OBJECT
public:
    explicit XModel(QList<int> *valuelist, QObject *parent = 0);
    virtual ~XModel();
    int rowCount(const QModelIndex &) const;
    int columnCount(const QModelIndex &) const;
    QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex &index) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
private:
    QList<int>* blah;
signals:

public slots:

;



XModel::XModel(QList<int> *valuelist, QObject *parent) :
    QAbstractListModel(parent),
    blah(valuelist)







XModel::~XModel()






int XModel::rowCount(const QModelIndex &) const

    return blah->size();


int XModel::columnCount(const QModelIndex &) const

    return 1;



QModelIndex XModel::index(int row, int column, const QModelIndex &parent) const

    return createIndex(row, column, (void)&(blah->at(row)));




QModelIndex XModel::parent(const QModelIndex &index) const

    return createIndex(index->row(), index->column(), NULL); 





QVariant XModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const

    return QVariant(blah->at(index.row()));

我什至必须使用QAbstractItemModel 还是QAbstractListModel 的工作方式完全相同?如何为模型提供实际数据的来源?这仅在data 函数内吗?请告诉我我做错了什么,我没有看到它并就如何正确地做到这一点提供建议,(好)howtos欢迎。

这是固定的,但是...

编辑:

Widget::Widget(QWidget *parent)
    : QWidget(parent),
    valuelist(),
    xm(&valuelist) //xm = XModel

    valuelist.append(1);
    valuelist.append(2);
    valuelist.append(3);
    valuelist.append(4);
    valuelist.append(5);
    valuelist.append(6);
    valuelist.append(7);
    valuelist.append(8);
    valuelist.append(9);

    view = new QListView(this);
    view->setModel(&xm);
    //how to force the XModel to reread the QList`?
    view->show();

【问题讨论】:

你能说得更具体一点,编译器错误吗?它说你没有实现什么功能? 我刚刚发现我使用了错误的查看器类,愚蠢:> 现在扩展问题.. 【参考方案1】:

在 XModel 中添加和删除数据,并让 XModel 为您修改底层列表(参考?):

Widget::Widget(QWidget *parent)
    : QWidget(parent),
    valuelist(),
    xm(&valuelist) //xm = XModel

    xm.append(1);
    xm.append(2);
    xm.append(3);
    xm.append(4);
    xm.append(5);
    xm.append(6);
    xm.append(7);
    xm.append(8);
    xm.append(9);

    view = new QListView(this);
    view->setModel(&xm);

    xm.append(10); // should call beginInsertRows, append to valuelist, and call endInsertRows.

    Q_ASSERT(valuelist.contains(10));

    view->show();

否则,您也许可以创建 QObject 和 QList 的组合,它们可以发出信号以通知 XModel 更改,但我认为第一种方法更好。

编辑:

这是一个愚蠢的例子。它将创建一个支持列表的模型,每秒将更多元素添加到列表中:

#include <QtGui/QApplication>
#include <QtGui/QListView>
#include <QtCore/QAbstractListModel>
#include <QtCore/QTimer>

class ListBackedModel : public QAbstractListModel

    Q_OBJECT
    QList<int>* m_list;

public:

    ListBackedModel(QList<int>* list, QObject* parent = 0)
        : QAbstractListModel(parent)
        , m_list(list)
    

    ~ListBackedModel()
    

    int rowCount(const QModelIndex &parent = QModelIndex()) const
    
        Q_UNUSED(parent);
        return m_list->size();
    

    QVariant data(const QModelIndex &index, int role) const
    
        if (index.row() >= rowCount())  return QVariant(); 
        if (index.row() < 0)  return QVariant(); 

        int element = m_list->at(index.row());

        if (Qt::DisplayRole == role) 
            return QString::number(element);
        

        if (Qt::ToolTipRole == role) 
            return tr("%1 is element #%2").arg(element).arg(index.row() + 1);
        

        return QVariant();
    

    void append(int element)
    
        /*
            First is the new index of the first element that will be inserted.
            Last is the new index of the last element that will be inserted.
            Since we're appending only one element at the end of the list, the
            index of the first and last elements is the same, and is equal to
            the current size of the list.
        */
        int first = m_list->size();
        int last = first;

        beginInsertRows(QModelIndex(), first, last);
        m_list->append(element);
        endInsertRows();
    

    void startAddingMoreElements()
    
        QTimer::singleShot(1000, this, SLOT(addMoreElements()));
    

private slots:

    void addMoreElements()
    
        append(qrand() % 100);
        startAddingMoreElements();
    
;


int main(int argc, char *argv[])

    QApplication a(argc, argv);

    QList<int> list;
    list << 1 << 10 << 34 << 111;
    ListBackedModel model(&list);

    QListView listView;
    listView.setModel(&model);
    listView.show();

    model.startAddingMoreElements();

    return a.exec();


#include "main.moc"

【讨论】:

顺便说一句,QLists 是隐式共享的......移动它们是免费的,复制是免费的,直到对副本进行第一次更改。 那么我必须传递哪些参数to void QAbstractItemModel::beginInsertRows ( const QModelIndex &amp; parent, int first, int last ) [protected] 尤其是 QModelIndex。 Qt Doc 说了一些关于 parent 的内容,但 parent(*) 本身需要另一个 QModelIndex。我有点困惑。 只有树模型需要父节点。对于表和列表,传递一个默认构造值 QModelIndex()。 beginInsertRows 的文档有一个很好的说明,解释了 first 和 last 的含义。 (doc.qt.nokia.com/4.6/qabstractitemmodel.html#beginInsertRows) 这不起作用,我不知道为什么... void XModel::append(const int &t) beginInsertRows(QModelIndex(), 0, 0);等等->追加(t); endInsertRows(); 还用 1,1 测试了第一个,最后一个 如果你传递 0, 0,你是在告诉 Qt 你在模型中添加一个元素。但是随后您将一个元素附加到内部列表 - 这打破了列表视图的期望。如果您通过 (..., 0, 0),请使用 QList::prepend。如果你使用 QList::append,传递 (..., blah->size(), blah->size())。见上面的代码。

以上是关于给定填充 ro QList 的 Qt 模型视图的主要内容,如果未能解决你的问题,请参考以下文章

Qt 嵌套模型视图

Qt容器类的对象模型及应用(线性结构篇:对于QList来说,sharable默认是false的,但对于接下来讲的QVector来说,sharable默认是true)

在 Qt 模型/视图中修改数据表示

Qt - 我自己的自定义对象的 QListView

模型中的 Qt 模型?

Qt ListView 不显示 C++ 模型内容