PDA

View Full Version : setCellWidget - strange behavior



Archa4
27th April 2011, 09:58
I created a Class based on QWidget. This Class represents the element i want to use as a QTableWidget element. I use setCellWidget to set this item. The strange behavior I'm talking about: when i set this custom widget to the 0, 0 cell - everything work fine. If i set this widget to the 0, 1 cell (0 row, 1 column), the things I've drawn in custom Widget are shifting to the right. If I set this widget to the 1, 0 cell, then it shifts to the bottom... Here are some pictures as well as the relevant code:

WeekCalendarWidget.cpp

#include "weekcalendarwidget.h"

WeekCalendarWidget::WeekCalendarWidget(QWidget *parent) :
QTableWidget(parent)
{
this->setColumnCount(7);
this->setRowCount(2);
date = QDate::currentDate();
this->verticalHeader()->hide();
this->horizontalHeader()->hide();
this->setSpan(0, 1, 1, 5);


str = "<";
tableItem = createItem(str);
this->setItem(0, 0, tableItem);


str = ">";
tableItem = createItem(str);
this->setItem(0, 6, tableItem);



/*
QWidget *asdsa = new WeekCalendarWidgetItem("0", "0");
this->setCellWidget(0, 1, asdsa);
*/


connect(this, SIGNAL(cellClicked(int,int)), this, SLOT(changeWeek(int, int)));

this->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
countForCalendar();
this->setRowHeight(1, 50);
this->setSelectionMode(QAbstractItemView::SingleSelectio n);
}





void WeekCalendarWidget::changeWeek(int row, int column)
{
if (row==0 && column==0)
{
date = date.addDays(-7);
countForCalendar();
}

else if (row==0 && column==6)
{
date = date.addDays(7);
countForCalendar();
}
}

void WeekCalendarWidget::countForCalendar()
{
int weekNumber = date.weekNumber();
str = "Year " + QString::number(date.year()) + " Week " + QString::number(weekNumber);
tableItem = createItem(str);
this->setItem(0, 1, tableItem);
str.setNum(date.day());

tableItem = createItem(str);
this->setItem(1, date.dayOfWeek()-1, tableItem);



QDate date2 = date;
int i = date2.dayOfWeek();

while (i>1)
{
date2 = date2.addDays(-1);
str.setNum(date2.day());
tableItem = createItem(str);
this->setItem(1, date2.dayOfWeek()-1, tableItem);
i = date2.dayOfWeek();
}

date2 = date;
i = date2.dayOfWeek();
while (i<7)
{
date2 = date2.addDays(1);
str.setNum(date2.day());
tableItem = createItem(str);
this->setItem(1, date2.dayOfWeek()-1, tableItem);
i = date2.dayOfWeek();
}
}

QTableWidgetItem * WeekCalendarWidget::createItem(QString string)
{
QTableWidgetItem *tableItem2 = new QTableWidgetItem(string);
tableItem2->setTextAlignment(Qt::AlignCenter);
tableItem2->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
return tableItem2;
}

WeekCalendarWidget::~WeekCalendarWidget()
{

}

void WeekCalendarWidget::test(QWidgetList *lista)
{
asd = lista;
}


WeekCalendarWidgetItem.cpp:

#include "weekcalendarwidgetitem.h"
#include <QtGui>

WeekCalendarWidgetItem::WeekCalendarWidgetItem(QSt ring date_par, QString number_par, QWidget *parent)
: QWidget(parent)
{
date = date_par;
number = number_par;


}

void WeekCalendarWidgetItem::paintEvent(QPaintEvent *event)
{

painter = new QPainter(this);

painter->drawText(this->geometry(), Qt::AlignTop, date);
painter->drawLine(this->geometry().topRight(), this->geometry().bottomLeft());
painter->drawText(this->geometry(), Qt::AlignBottom|Qt::AlignRight, number);


}

WeekCalendarWidgetItem::~WeekCalendarWidgetItem()
{

}

Normal View, where I was using only default setItem function:
6299

View, where I set custom Widget to the 0-0 cell:
6300

View, where I set custom Widget to the 0-1 cell:
6301

View, where I set custom Widget to the 1-0 cell:
6302

If anyone has any idea Why this is happening, I would really like to hear it!

wysota
27th April 2011, 10:07
Please provide a minimal compilable example reproducing the problem.

Archa4
27th April 2011, 10:12
I think this should do it
6303

It's very interesting, that I thought the problem would be to resize the custom widget to the size of the cell, but It seems like custom Widget resizes to the cell size, but it just isn't placed right. It shifts to the right multi played by the column number it should be inserted in, and it shifts to the bottom multi played by the row number it should be inserted in...

Another thing, when i close application I get this line:
QPaintDevice: Cannot destroy paint device that is being painted
If while the app was working I selected the cell containing the widget...

Archa4
27th April 2011, 14:50
Still no one?

AlexSudnik
27th April 2011, 17:09
What's the point in using QWidget::geometry() in the paintEvent ? What happens here is that you're drawing your graphics in the bounding rectangle which is the offset that an item has within the tableWidget , while using a coordinate system of the item itself.So kind of double offset takes place here.

You paintEvent should look like this instead:



void WeekCalendarWidgetItem::paintEvent(QPaintEvent *event)
{
QPainter painter(this);

QRect bound = event -> rect(); // bounding box of an item to be painted

painter.save();

// example
painter.drawLine( bound.bottomLeft() , bound.topRight() );
//

painter.restore();

}




QPaintDevice: Cannot destroy paint device that is being painted

Ouch, be carefull with the QPainter instances you're creating : every time your item will have to be repainted,you've got a new QPainter instance allocated dynamically : it will not cause a memory leak since it's parented BUT each instance will be kept in memory,unless parent is destroyed or instance is deleted manually. So you can either create QPainter object locally or use a QScopedPointer.

Archa4
28th April 2011, 08:26
Very Big THANKS!