关于qtablewidgetitem-setitemprototype的理解

在《C++ Gui Programming with Qt4》中第4章,SpreadSheet例子中,Cell继承自QTableWidgetItem类,SpreadSheet继承自QTableWidget类,在SpreadSheet中通过调用setItemPrototype方法设置SpreadSheet的项类--Cell,保证在用户点击时,自动生成Cell实例(instance)来保存用户输入的数据。

SpreadSheet::SpreadSheet(QWidget *parent) :    QTableWidget(parent),
    pActionActive(new QAction(this)),
    mIsSaved(false),
    mAutoRecalculated(false)
{
    setActionActive();

    //设置Cell类为SpreadSheet的项类.
    setItemPrototype(new Cell());

    connect(this, static_cast<void (SpreadSheet::*)(QTableWidgetItem*)>(&SpreadSheet::itemChanged),
            this, static_cast<void (SpreadSheet::*)()>(&SpreadSheet::somethingChanged));

    clear();
}

当用户在生成的类excel表格中点击项,则会自动生成Cell实例,保存用户的输入内容。

但是在第十章的CoordinateSettor例子中,在根据系统录入的10组坐标中,则是在后台直接创建item实例,填入在表格中的位置,然后再将坐标信息填写到item中,

将item实例填到表格中。

void TestTableWidget::addRow(){
    //pTableWidget为QTableWidget实例。
    int row(pTableWidget->rowCount());
    pTableWidget->insertRow(row);

    QTableWidgetItem* item0(new QTableWidgetItem());
    item0->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft);
    pTableWidget->setItem(row, 0, item0);

    QTableWidgetItem* item1(new QTableWidgetItem());
    item1->setTextAlignment(Qt::AlignBaseline | Qt::AlignRight);
    pTableWidget->setItem(row, 1, item1);

    pTableWidget->setCurrentCell(row, 0);

}

如果想向SpreadSheet那样自动生成item项,则必须调用其setItemPrototype方法。

TestTableWidget::TestTableWidget(const QList<QPointF>* coord,                                 QWidget *parent) :
    QWidget(parent),
    pTableWidget(new QTableWidget(0, 2, this))
{
    pCoordinates = coord;
    QStringList strList;
    strList.append(tr("X"));
    strList.append(tr("Y"));

    pTableWidget->setHorizontalHeaderLabels(strList);
    pTableWidget->setItemPrototype(new QTableWidgetItem());

    for (int row(0); row != pCoordinates->count(); ++row) {
        QPointF point = pCoordinates->at(row);
        addRow();

        pTableWidget->item(row, 0)->setText(QString::number(point.x()));
        pTableWidget->item(row, 1)->setText(QString::number(point.y()));
    }

    QVBoxLayout* vBoxLayout(new QVBoxLayout(this));
    vBoxLayout->addWidget(pTableWidget);
    setLayout(vBoxLayout);
}

发现执行到

pTableWidget->item(row, 0)->setText(QString::number(point.x()));

就会报告异常,怀疑setItemPrototype方法中只是制定当用户点击项时,系统自动创建项,而程序要往表格中填写内容时,必须创建项实例并添加到表格中。 后查看QTableWidget的api,setItemPrototype方法中要求实现QTableWidgetItem的derived class。感觉不能直接调用QTableWidgetItem的实例,故在此处创建class ItemClone,并实现clone方法。

QTableWidgetItem* ItemClone::clone() const{
    return new ItemClone();
}

然后将ItemClone 放到setItemPrototype方法中。这时候再运行程序就一切正常了。当表格中没有创建项实例时,用户手动点击表格,自动就会有项实例生成,保存信息。

以下是具体实现code

main

#include <QtWidgets>
#include "coordinatesetter.h"
#include "testtablewidget.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QList<QPointF> coordinates;
    coordinates << QPointF(0.0, 0.9)
                << QPointF(0.2, 11.0)
                << QPointF(0.4, 15.4)
                << QPointF(0.6, 12.9)
                << QPointF(0.8, 8.5)
                << QPointF(1.0, 7.1)
                << QPointF(1.2, 4.0)
                << QPointF(1.4, 13.6)
                << QPointF(1.6, 22.2)
                << QPointF(1.8, 22.2);
    //CoordinateSetter coordinateSetter(&coordinates);
    //coordinateSetter.show();
    TestTableWidget coordinateSetter(&coordinates);
    coordinateSetter.show();

    return app.exec();
}

显示表格的类:头文件

#ifndef TESTTABLEWIDGET_H#define TESTTABLEWIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
class QTableWidget;
QT_END_NAMESPACE

class TestTableWidget : public QWidget
{
    Q_OBJECT
public:
    explicit TestTableWidget(const QList<QPointF>* coord, QWidget *parent = 0);

private:
    void addRow();

private:
    QTableWidget* pTableWidget;
    const QList<QPointF>* pCoordinates;
};

#endif // TESTTABLEWIDGET_H

显示表格的类:实现文件

#include "testtablewidget.h"
#include <QTableWidget>
#include <QStringList>
#include <QTableWidgetItem>
#include <QVBoxLayout>

#include "itemclone.h"

TestTableWidget::TestTableWidget(const QList<QPointF>* coord,
                                 QWidget *parent) :
    QWidget(parent),
    pTableWidget(new QTableWidget(0, 2, this))
{
    pCoordinates = coord;
    QStringList strList;
    strList.append(tr("X"));
    strList.append(tr("Y"));

    pTableWidget->setHorizontalHeaderLabels(strList);
    pTableWidget->setItemPrototype(new ItemClone());
    //set pTableWidget to be disabled for changing item.
    //pTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

    for (int row(0); row != pCoordinates->count(); ++row) {
        QPointF point = pCoordinates->at(row);
        addRow();

        //pTableWidget->item(row, 0)->setData(Qt::DisplayRole, QString::number(point.x()));
        pTableWidget->item(row, 0)->setText(QString::number(point.x()));
        pTableWidget->item(row, 1)->setText(QString::number(point.y()));
    }

    QVBoxLayout* vBoxLayout(new QVBoxLayout(this));
    vBoxLayout->addWidget(pTableWidget);
    setLayout(vBoxLayout);
}

void TestTableWidget::addRow()
{
    //pTableWidget为QTableWidget实例。
    int row(pTableWidget->rowCount());
    pTableWidget->insertRow(row);

    ItemClone* item0(new ItemClone());
    item0->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft);
    pTableWidget->setItem(row, 0, item0);

    ItemClone* item1(new ItemClone());
    item1->setTextAlignment(Qt::AlignBaseline | Qt::AlignRight);
    pTableWidget->setItem(row, 1, item1);

    pTableWidget->setCurrentCell(row, 0);
}

QTableWidgetItem的derived类:头文件

#ifndef ITEMCLONE_H#define ITEMCLONE_H

#include <QTableWidgetItem>

class ItemClone : public QTableWidgetItem
{
public:
    ItemClone();

    virtual QTableWidgetItem* clone() const;
};

#endif // ITEMCLONE_H

QTableWidgetItem的derived类:实现文件

#include "itemclone.h"
ItemClone::ItemClone()
{
}

QTableWidgetItem* ItemClone::clone() const
{
    return new ItemClone();
}

如coder要测试是否自动创建项实例,而不是程序写的

可以将addRow方法修改为:

void TestTableWidget::addRow()
{
    //pTableWidget为QTableWidget实例。
    int row(pTableWidget->rowCount());
    pTableWidget->insertRow(row);
}

这样只是对表格插入行,但是每行中的项实例没有创建,只有运行程序,用户在表格中点击输入时,才会生成项对象。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值