在《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* 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
#include "coordinatesetter.h"
#include "testtablewidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QList 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
QT_BEGIN_NAMESPACE
class QTableWidget;
QT_END_NAMESPACE
class TestTableWidget : public QWidget
{
Q_OBJECT
public:
explicit TestTableWidget(const QList* coord, QWidget *parent = 0);
private:
void addRow();
private:
QTableWidget* pTableWidget;
const QList* pCoordinates;
};
#endif // TESTTABLEWIDGET_H
显示表格的类:实现文件
#include "testtablewidget.h"
#include
#include
#include
#include
#include "itemclone.h"
TestTableWidget::TestTableWidget(const QList* 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
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);
}
这样只是对表格插入行,但是每行中的项实例没有创建,只有运行程序,用户在表格中点击输入时,才会生成项对象。