• 14901阅读
  • 10回复

关于QAbstractItemModel::insertRow [复制链接]

上一主题 下一主题
离线cwbcwb505
 
只看楼主 正序阅读 楼主  发表于: 2008-11-13
— 本帖被 XChinux 从 General Qt Programming 移动到本区(2011-01-02) —
我的目录很简单,自己建一个类来继承这个类,实现随时插入一行,并同时在treeView里显示出来,也是我将QAbstractItemModel::insertRow 给重写了,代码如下:
bool treeView::insertRow(int inRow, const QModelIndex & iParent /* = QModelIndex */)
{
    viewItem* lptypParentItem;
    viewItem* lptypChild = new viewItem();
    if (!iParent.isValid())
    {
        lptypParentItem = mptypRootItem;
    }
    else
    {
        lptypParentItem = static_cast<viewItem*>(iParent.internalPointer());
    }

    lptypChild->setParent(lptypParentItem);
    if (true == lptypParentItem->insertChild(inRow, lptypChild))
    {
        return true;
    }
    else
    {
        return false;
    }

}

可是我却出现了一个问题就是,当我向里面插入一行时,treeView里面显示的视图并没有增加一行,而是将以前老的最后行给挤出去,也就是说treeView不知道行数已经曾加了,而只知道是数据更新了,例如现有以下三行:
1
2
3
调用treeModel::insertRow( 0 )以后,就是以下的现象:

1
2
空行出现在了0的位置,其它的三行分别往下移了,但是3却不见了,因为视图没有为它们增加行!还有一点的就是视图也不知道何时更新数据,每次插入行之后都要让窗口重画后才能看到变化,这个也不知道怎么弄!请各位大侠指点;
离线wvins
只看该作者 10楼 发表于: 2008-11-14
你把代码打个包多好,
害我贴的辛苦。
看看
离线water_wf

只看该作者 9楼 发表于: 2008-11-13
那也又可能,对c++的语法,也记不清楚了
离线water_wf

只看该作者 8楼 发表于: 2008-11-13
那也又可能,对c++的语法,也记不清楚了
离线cwbcwb505
只看该作者 7楼 发表于: 2008-11-13
老兄,我觉得这个函数是可以重写的!因为QStandardItemModel就重写了这个函数!只是我不能用基类的指针来调用它而已
离线cwbcwb505
只看该作者 6楼 发表于: 2008-11-13
哦,谢谢了,又给了我很大的启发,我还得去研究一下。
离线water_wf

只看该作者 5楼 发表于: 2008-11-13
1:我是说这个接口不能继承的,不是virtual 的,如果这样,你可以直接用QAbstractItemModel::insertRow 啊,为什么要自己写呢
2: 如果有数据有变化,要自己通知QTreeView更新的比如tree->reset()
离线cwbcwb505
只看该作者 4楼 发表于: 2008-11-13
老兄,请问你说的那个不是虚拟的是什么意思呀?你要是觉得得奇怪我为什么编译通得过你可以拷过去编译试试看呀,以下是我调它的代码:
class modeTest : public QWidget
{
    Q_OBJECT

public:
    modeTest(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~modeTest();
private:
    Ui::modeTestClass  ui;
    treeView*          model;
private slots:
    void on_pushButton_clicked();
};

modeTest::modeTest(QWidget *parent, Qt::WFlags flags)
    : QWidget(parent, flags)
{
    ui.setupUi(this);
    model = new treeView();
    ui.treeView->setModel(model);

    model->setColumnCount(3);
    model->insertRow(0);
    model->setData(model->index(0, 0), "1");
    model->setData(model->index(0, 1), "2");
    model->setData(model->index(0, 2), "3");

}

void modeTest::on_pushButton_clicked()
{
                      QString lsz1;
    QString lsz2;
    QString lsz3;

    model->insertRow(0);

    lsz1 = ui.lineEdit->text();
    lsz2 = ui.lineEdit_2->text();
    lsz3 = ui.lineEdit_3->text();

    model->setData(model->index(0, 0), lsz1);
    model->setData(model->index(0, 1), lsz2);
    model->setData(model->index(0, 2), lsz3);
}

以上的调用,我在构靠函数里面调用完全正常!只是在void modeTest::on_pushButton_clicked()
里面的调用有异常!
离线water_wf

只看该作者 3楼 发表于: 2008-11-13
这个接口好像不是虚拟的,更奇怪你能编译通过?
离线cwbcwb505
只看该作者 2楼 发表于: 2008-11-13
class CTreeView : public QAbstractItemModel
{
public:
    CTreeView();
    ~CTreeView();

    QVariant data(const QModelIndex& iIndex, int inRole)const;
    QVariant headerData(int inSection, Qt::Orientation iOrientation, int inRole = Qt::DisplayRole)const;
    QModelIndex index(int inRow, int inColumn, const QModelIndex& ipParent = QModelIndex())const;
    QModelIndex parent(const QModelIndex& iIndex)const;
    int rowCount(const QModelIndex& iParent = QModelIndex())const;
    int columnCount(const QModelIndex &iParent = QModelIndex()) const;
    bool setHeaderData ( int inSection, Qt::Orientation iOrientation, const QVariant & istlValue, int inRole = Qt::EditRole);
    void setColumnCount(int inCount);
    bool insertRow (int inRow, const QModelIndex & iParent = QModelIndex());
    bool setData ( const QModelIndex & iIndex, const QVariant & istlValue, int inRole = Qt::EditRole );
    void clear();

private:
    CViewItem* mptypRootItem;
};

CTreeView::CTreeView()
{
    mptypRootItem = new CViewItem();
}

CTreeView::~CTreeView()
{
    delete mptypRootItem;
}

QModelIndex CTreeView::index(int inRow, int inColumn, const QModelIndex& iParent /* = QModelIndex */)const
{
    CViewItem*  lptypParentItem;
    CViewItem * lptypChildItem;

    if (!hasIndex(inRow, inColumn, iParent))
    {
        return QModelIndex();
    }

    if (!iParent.isValid())
    {
        lptypParentItem = mptypRootItem;
    }
    else
    {
        lptypParentItem = static_cast<CViewItem*>(iParent.internalPointer());
    }

    lptypChildItem = lptypParentItem->child(inRow);
    if (lptypChildItem)
    {
        return createIndex(inRow, inColumn, lptypChildItem);
    }
    else
    {
        return QModelIndex();
    }
}

QModelIndex CTreeView::parent(const QModelIndex& iIndex)const
{
    CViewItem*  lptypChildItem;
    CViewItem*  lptypParent;

    if (!iIndex.isValid())
    {
        return QModelIndex();
    }

    lptypChildItem = static_cast<CViewItem*>(iIndex.internalPointer());
    lptypParent = lptypChildItem->parent();
    if (lptypParent == mptypRootItem)
    {
        return QModelIndex();
    }
    else
    {
        return createIndex(lptypParent->row(), 0, lptypParent);
    }
}

int CTreeView::rowCount(const QModelIndex& iParent /* = QModelIndex */)const
{
    CViewItem*  lptypParentItem;

    if (iParent.column() > 0)
    {
        return 0;
    }

    if (!iParent.isValid())
    {
        lptypParentItem = mptypRootItem;
    }
    else
    {
        lptypParentItem = static_cast<CViewItem*>(iParent.internalPointer());
    }

    return lptypParentItem->childCount();
}

int CTreeView::columnCount(const QModelIndex& iParent /* = QModelIndex */)const
{
    if (iParent.isValid())
    {
        return static_cast<CViewItem*>(iParent.internalPointer())->columnCount();
    }
    else
    {
        return mptypRootItem->columnCount();
    }
}

QVariant CTreeView::data(const QModelIndex& iIndex, int inRole)const
{
    if (!iIndex.isValid())
    {
        return QVariant();
    }
    if (inRole != Qt::DisplayRole)
    {
        return QVariant();
    }

    CViewItem* lptypItem = static_cast<CViewItem*>(iIndex.internalPointer());
    return lptypItem->data(iIndex.column());
}

QVariant CTreeView::headerData(int inSection, Qt::Orientation iOrientation, int inRole /* = QT::DisplayRole */)const
{
    if (iOrientation == Qt::Horizontal && inRole == Qt::DisplayRole)
    {
        return mptypRootItem->data(inSection);
    }

    return QVariant();

}

void CTreeView::setColumnCount(int inCount)
{
    if(inCount <= 0)
        return;

    mptypRootItem->cleanData();
    for (int i = 0; i < inCount; ++i)
    {
        mptypRootItem->setData(i, QString("%1").arg(i));
    }
    headerDataChanged(Qt::Horizontal, 0, inCount - 1);
}

bool CTreeView::setHeaderData(int inSection, Qt::Orientation iOrientation, const QVariant & istlValue, int inRole /* = Qt::EditRole  */)
{
    if (true == mptypRootItem->setData(inSection, istlValue))
    {
        headerDataChanged(iOrientation, inSection, inSection);
        return true;
    }
    else
    {
        return false;
    }
}

bool CTreeView::insertRow(int inRow, const QModelIndex & iParent /* = QModelIndex */)
{
    CViewItem* lptypParentItem;
    CViewItem* lptypChild = new CViewItem();
    if (!iParent.isValid())
    {
        lptypParentItem = mptypRootItem;
    }
    else
    {
        lptypParentItem = static_cast<CViewItem*>(iParent.internalPointer());
    }

    lptypChild->setParent(lptypParentItem);
    if (true == lptypParentItem->insertChild(inRow, lptypChild))
    {
        return true;
    }
    else
    {
        return false;
    }

}

bool CTreeView::setData(const QModelIndex & iIndex, const QVariant & istlValue, int inRole /* = Qt::EditRole  */)
{
    int lnColumn;
    if(!iIndex.isValid())
        return false;

    CViewItem* lptypItem = static_cast<CViewItem*>(iIndex.internalPointer());
    lnColumn = iIndex.column();
    lptypItem->setData(lnColumn, istlValue, lptypItem->parent());
    return true;
}

void CTreeView::clear()
{
    mptypRootItem->eraseChild();
}

这就是我完整的model类了,虽然都没有注释,不过这些类都是重写的QAbstractItemModel的方法,请各位大侠多多指点!
                 
                                                              谢谢!
离线cwbcwb505
只看该作者 1楼 发表于: 2008-11-13
还是将我完整的代码贴出来一下吧:
class CViewItem
{
public:
    CViewItem();
    ~CViewItem();
    void appendChild(CViewItem* itypChild);
    CViewItem* child(int inRow)const;
    int row()const;
    int childCount()const;
    int columnCount()const;
    QVariant data(int inColumn)const;
    CViewItem* parent()const;
    bool setData(int inColumn, const QVariant& istlValue, CViewItem* iptypParent = NULL);
    bool insertChild(int inPosition, CViewItem* iptypChild);
    bool setParent(CViewItem* iptypParent);
    void cleanData();
    void eraseChild();

private:
    CViewItem*          mptypParentItem;
    QList<QVariant>    mstlData;
    QList<CViewItem*>    mstlChildItem;
};

#include "viewItem.h"

CViewItem::CViewItem()
{

}

CViewItem::~CViewItem()
{
    qDeleteAll(mstlChildItem);
}

void CViewItem::appendChild(CViewItem* itypChild)
{
    mstlChildItem.append(itypChild);
}

CViewItem* CViewItem::child(int inRow)const
{
    return mstlChildItem.value(inRow);
}

int CViewItem::row()const
{
    if (mptypParentItem)
    {
        return mptypParentItem->mstlChildItem.indexOf(const_cast<CViewItem*>(this));
    }
    else
    {
        return 0;
    }
}

int CViewItem::childCount()const
{
    return mstlChildItem.count();
}

int CViewItem::columnCount()const
{
    return mstlData.count();
}

QVariant CViewItem::data(int inColumn)const
{
    return mstlData.value(inColumn);
}

CViewItem* CViewItem::parent()const
{
    return mptypParentItem;
}

bool CViewItem::setData(int inColumn, const QVariant& istlValue, CViewItem* iptypParent /* = NULL */)
{
    mptypParentItem = iptypParent;
    if (inColumn < mstlData.count())
    {
        mstlData.replace(inColumn, istlValue);
        return true;
    }
    else if (inColumn == mstlData.count())
    {
        mstlData.push_back(istlValue);
        return true;
    }
    else
    {
        return false;
    }
}

void CViewItem::cleanData()
{
    mstlData.clear();
}

bool CViewItem::insertChild(int inPosition, CViewItem* itypChild)
{
    if (inPosition < 0)
    {
        return false;
    }
    else if (inPosition < mstlChildItem.count())
    {
        mstlChildItem.insert(inPosition, itypChild);
    }
    else
    {
        appendChild(itypChild);
    }

    return true;
}

bool CViewItem::setParent(CViewItem* iptypParent)
{
    mptypParentItem = iptypParent;
    return true;
}

void CViewItem::eraseChild()
{
    mstlChildItem.erase(mstlChildItem.begin(), mstlChildItem.end());
}

以上是我的model的数据类
快速回复
限100 字节
 
上一个 下一个