PDA

View Full Version : QTableWidget+QTableWidgetItem trouble



Fastman
7th November 2007, 15:51
code(QT 4.3.1):



void HSM::setTable()
{

ui.tableWidget->setRowCount(30);
ui.tableWidget->setColumnCount(10);

ui.tableWidget->setHorizontalHeaderLabels(
QStringList() << tr("Task")
<< tr("Time")
<< tr("Group")
<< tr("Object")
<< tr("File")
<< tr("ID_OBJ")
<< tr("State")
<< tr("Prc")
<< tr("ID_SYS")
<< tr("RootPath"));

Items = new QTableWidgetItem(tr("Task"),QTableWidgetItem::Type);
Items->setIcon(QIcon(QPixmap(":/HSM/Resources/Add.png")));

ui.tableWidget->resizeRowsToContents();
ui.tableWidget->resizeColumnsToContents();
}




void HSM::setTableData()
{

for (int row = 0 ; row < ui.tableWidget->rowCount() ;++row)
{
ui.tableWidget->setItem(row,0,Items);
}
ui.tableWidget->resizeRowsToContents();
ui.tableWidget->resizeColumnsToContents();

}



All well works but at closing the app the mistake jumps out.

The mistake occurs here:

d:\qt4\src\gui\itemviews\qtablewidget.cpp


void QTableModel::clearContents()
{
for (int i = 0; i < tableItems.count(); ++i) {
if (tableItems.at(i)) {
tableItems.at(i)->view = 0;
delete tableItems.at(i); <--ERROR
tableItems[i] = 0;
}
}
reset();
}


and tableItems.count() = 300. (10*30 ????)
but i'am have only 30 items !!!

Where at me a mistake. Also what it is necessary to make to correct a code?

jpn
7th November 2007, 16:02
Yes, you do actually have 30*10=300 items. The mistake is that you set the same single item into every cell. You should create a separate item into each cell:


void HSM::setTableData()
{

for (int row = 0 ; row < ui.tableWidget->rowCount() ;++row)
{
QTableWidgetItem* item = new QTableWidgetItem(tr("Task"));
item->setIcon(QIcon(QPixmap(":/HSM/Resources/Add.png")));
ui.tableWidget->setItem(row,0,item);
}
ui.tableWidget->resizeRowsToContents();
ui.tableWidget->resizeColumnsToContents();

}

Fastman
7th November 2007, 16:07
i'am stupid :)
Thx !

Fastman
9th November 2007, 10:42
Yes, you do actually have 30*10=300 items. The mistake is that you set the same single item into every cell. You should create a separate item into each cell:


void HSM::setTableData()
{

for (int row = 0 ; row < ui.tableWidget->rowCount() ;++row)
{
QTableWidgetItem* item = new QTableWidgetItem(tr("Task"));
item->setIcon(QIcon(QPixmap(":/HSM/Resources/Add.png")));
ui.tableWidget->setItem(row,0,item);
}
ui.tableWidget->resizeRowsToContents();
ui.tableWidget->resizeColumnsToContents();

}


Whether there will be memory leak if function setTableData () is caused in me each 5 seconds for display of changes in the table?

jpn
9th November 2007, 10:49
No, that shouldn't leak memory since QTableWidget deletes the old item if you set a new item into cell. But you definitely don't want to re-create all the items every time in setTableData(). Create the items once in constructor or so, and just set the data in setTableData():


QTableWidgetItem* item = ui.tableWidget->item(row, col);
item->setSomething(...);

Fastman
9th November 2007, 11:41
No, that shouldn't leak memory since QTableWidget deletes the old item if you set a new item into cell. But you definitely don't want to re-create all the items every time in setTableData(). Create the items once in constructor or so, and just set the data in setTableData():


QTableWidgetItem* item = ui.tableWidget->item(row, col);
item->setSomething(...);


Hmm... not work :(


class HSM : public QDialog
{
Q_OBJECT
...
...
...
private:
QTableWidgetItem* itemArchive;
QTableWidgetItem* itemRestore;
QTableWidgetItem* itemDelete;
...
...
...


HSM::HSM(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{

...
...
...
itemArchive = new QTableWidgetItem(tr("Archive"));
itemRestore = new QTableWidgetItem(tr("Restore"));
itemDelete = new QTableWidgetItem(tr("Delete"));
...
...
...



void HSM::setTableData()
{
sTskInfoGUI sTaskGUI;
db_work db;

sTaskGUI = db.GetTaskToGUI();
db.CloseDB();

for (int row = 0 ; row < sTaskGUI.nCmd.size() ;++row)
{

if (sTaskGUI.nCmd.at(row) == 1)
{
itemArchive = ui.tableWidget->item(row,0);
itemArchive->setIcon(QIcon(QPixmap(":/HSM/Resources/archive.png")));
itemArchive->setBackground(QColor::fromRgb(200,255,104,100));
//ui.tableWidget->setItem(row,0,itemArchive);

}
if (sTaskGUI.nCmd.at(row) == 2)
{
itemRestore = ui.tableWidget->item(row,0);
itemRestore->setIcon(QIcon(QPixmap(":/HSM/Resources/restore.png")));
itemRestore->setBackground(QColor::fromRgb(115,150,255,100));
//ui.tableWidget->setItem(row,0,itemRestore);
}
if (sTaskGUI.nCmd.at(row) == 3)
{
itemDelete = ui.tableWidget->item(row,0);
itemDelete->setIcon(QIcon(QPixmap(":/HSM/Resources/del.png")));
itemDelete->setBackground(QColor::fromRgb(255,100,120,100));
//ui.tableWidget->setItem(row,0,itemDelete);
}
...
...
...



Exception in code :
d:\qt4\src\gui\itemviews\qtablewidget.cpp

inline void QTableWidgetItem::setIcon(const QIcon &aicon)
{ setData(Qt::DecorationRole, aicon); }

jpn
9th November 2007, 11:49
QTableWidget::item() returns 0 which means there is no item in such cell and so you are dereferencing a null pointer. Did you actually call QTableWidget::setItem() anywhere?


itemArchive = new QTableWidgetItem(tr("Archive"));
itemRestore = new QTableWidgetItem(tr("Restore"));
itemDelete = new QTableWidgetItem(tr("Delete"));
ui.tableWidget->setItem(0,0,itemArchive); // <--
ui.tableWidget->setItem(1,0,itemRestore); // <--
ui.tableWidget->setItem(2,0,itemDelete); // <--

Fastman
9th November 2007, 12:28
QTableWidget::item() returns 0 which means there is no item in such cell and so you are dereferencing a null pointer. Did you actually call QTableWidget::setItem() anywhere?


itemArchive = new QTableWidgetItem(tr("Archive"));
itemRestore = new QTableWidgetItem(tr("Restore"));
itemDelete = new QTableWidgetItem(tr("Delete"));
ui.tableWidget->setItem(0,0,itemArchive); // <--
ui.tableWidget->setItem(1,0,itemRestore); // <--
ui.tableWidget->setItem(2,0,itemDelete); // <--


no effect :(

Exception in code :
d:\qt4\src\gui\itemviews\qtablewidget.cpp


inline void QTableWidgetItem::setIcon(const QIcon &aicon){ setData(Qt::DecorationRole, aicon); }

jpn
9th November 2007, 12:48
There are 3 places in your code in which you pick an item at certain cell:


...
itemArchive = ui.tableWidget->item(row,0);
...
itemRestore = ui.tableWidget->item(row,0);
...
itemRestore = ui.tableWidget->item(row,0);
...

On the other hand, you have created an item only into cells (0,0), (1,0) and (2,0). If "row" is anything else than 0-2, you'll get a crash. This is most likely the case of yours.

Fastman
9th November 2007, 14:18
Ok :) Thx for you help :)

jpn
9th November 2007, 18:42
Let me correct one thing. I just re-read my previous message and I want to make sure I don't get misundestood. Of course, calling QTableWidget::item() with any possible parameters doesn't cause a crash:

QTableWidgetItem* item = tableWidget->item(1234, 5678);
But the point is that in case no item exists in such cell, QTableWidget::item() returns 0. Then, dereferencing a null pointer is what causes the crash:

item->setSomething();

Fastman
9th November 2007, 19:06
How to make so that last column it was leveled by a right edge of the table ?


void HSM::setTableData()
{
sTskInfoGUI sTaskGUI;
db_work db;

sTaskGUI = db.GetTaskToGUI();
db.CloseDB();...
...
...
itemRootPatch->setText(sTaskGUI.cRootPath.at(row));
ui.tableWidget->setItem(row,9,itemRootPatch);
}

ui.tableWidget->resizeRowsToContents();
ui.tableWidget->resizeColumnsToContents();

}

Here so my form looks.

jpn
9th November 2007, 19:24
You can either use QHeaderView::setResizeMode() and pass QHeaderView::Stretch:

ui.tableWidget->horizontalHeader()->setResizeMode(10, QHeaderView::Stretch);
Or you can use a "shortcut" (which QTreeView uses by default):

ui.tableWidget->horizontalHeader()->setStretchLastSection(true);

Fastman
10th November 2007, 13:19
many Thx ! :)