PDA

View Full Version : QTableView: sizeHint() not getting invoked for custom delegate



montylee
17th February 2009, 20:48
I have a QTableView and i am using a custom delegate to display the content in the table view. I have subclassed the QStyledItemDelegate class and reimplemented the paint() function. Now, i want to increase the height of the table view row so that only 8 rows are visible at a time. I tried reimplementing the sizeHint() function of QStyledItemDelegate class but it's not getting invoked at all. I even added exit(1) inside the function to check if it is being invoked.

I don't get why it's not being called. I reimplemented the paint function and it's called automatically so what's the problem with sizeHint()?

wysota
18th February 2009, 00:26
How does the reimplementation look like?

montylee
18th February 2009, 01:17
reimplementation of sizeHint() is empty for now. I am just having a qDebug() statement and exit(1) in sizeHint() to check if the function is actually getting called. But nothing is displayed and my program doesn't exit.

I am setting some options for the table view like allowing single selection, hiding headers etc. Can this be the reason that sizeHint() is not being called? It seems idiotic to me but this thought came to my mind.

Here's how i am reimplementing sizeHint():

Header file:

class CustomDelegate : public QAbstractItemDelegate
{
public:
CustomDelegate(QObject *parent=0);
// Public member functions
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

C++ file:

void CustomDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
// Paint implementation
}

QSize CustomDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
qDebug("Inside sizeHint");
exit(1);
}


Now, when i run my application, paint() is called but sizeHint() is not getting called. I don't why sizeHint() is not being called :(

aamer4yu
18th February 2009, 04:18
2 questions -
Have you added any data to the tableview ?
If you are using your model, try playing with sizeHintRole.

second, what if you inherit from QItemDelegate instead of QAbstractItemDelegate ?

montylee
18th February 2009, 18:22
2 questions -
Have you added any data to the tableview ?
If you are using your model, try playing with sizeHintRole.

second, what if you inherit from QItemDelegate instead of QAbstractItemDelegate ?
yup, i have added data in the model and it's displayed properly in the table view.
I even added code for sizeHintRole in the data() function of the model, still it doesn't execute the code inside sizeHintRole.
Don't know what's wrong. sizeHint() is supposed to be called automatically i guess.

I tried inhering from QAbstractItemDelegate, QStyledItemDelegate and QItemDelegate but none of these seem to work for sizeHint.

I'll try to reproduce the problem in a separate application and try to post it here.

BTW, here's the flags() function code from my model. Don't know if this has anything to do with my problem.



Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;

if (index.column() == CHECKBOX_COLUMN)
{ // Make the checkbox column items checkable
return QAbstractTableModel::flags(index) | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
}
else
{
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}
}

Is there any other way to set the height of rows in the table view? Basically my requirement is to increase the row height so that only 8 rows are visible in the table at a time without scrolling.

montylee
18th February 2009, 18:46
Here's a sample code which reproduces the problem:



#include <QApplication>
#include <QListView>
#include <QTableView>
#include <QAbstractItemDelegate>
#include <QStandardItemModel>
#include <QPainter>
class PluginDelegate : public QAbstractItemDelegate {
public:
PluginDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const{
if(option.state & QStyle::State_Selected){
painter->fillRect(option.rect, option.palette.color(QPalette::Highlight));
}
QIcon ic = QIcon(qvariant_cast<QPixmap>(index.data(Qt::DecorationRole)));
QString txt = index.data(Qt::DisplayRole).toString();
QRect r = option.rect.adjusted(2, 2, -2, -2);
ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft);
r = r.adjusted(r.height()+20, 0, 0, 0);
painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignVCenter|Qt::AlignLeft|Qt::TextWordWrap, txt, &r);
}
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const{
qDebug("in sizeHint()");
exit(1);
//return QSize(200, 82); // very dumb value
}

};

int main(int argc, char **argv){
QApplication app(argc, argv);
//QListView lv;
QTableView lv;
QStandardItemModel model;
model.setRowCount(2);
model.setColumnCount(1);
model.setData(model.index(0, 0), QPixmap("/usr/share/icons/crystalsvg/32x32/actions/filenew.png"), Qt::DecorationRole);
model.setData(model.index(0, 0), "Some wonderful text which is long enough to cover more than one row");
model.setData(model.index(1, 0), QPixmap("/usr/share/icons/crystalsvg/32x32/actions/exit.png"), Qt::DecorationRole);
model.setData(model.index(1, 0), "Some wonderful text");
lv.setModel(&model);
lv.setItemDelegate(new PluginDelegate(&lv));
lv.setAlternatingRowColors(true);
lv.show();
return app.exec();
}


If i use table view in the above code, sizeHint() is not called at all. But if i replace table view with a list view, sizeHint() is called and the row height is set properly.

wysota
18th February 2009, 18:54
What happens if you hide the headers?

montylee
18th February 2009, 20:19
What happens if you hide the headers?
sorry, i didn't get what you mean.
The headers of my table are hidden and hiding/displaying the headers have no difference in the sample application i posted.

wysota
18th February 2009, 21:09
Call QTableView::resizeRowsToContents() and QTableView::resizeColumnsToContents().

montylee
19th February 2009, 00:31
Call QTableView::resizeRowsToContents() and QTableView::resizeColumnsToContents().
i can try using QTableView::resizeRowsToContents() but i am not sure it will work for me properly. I am drawing the text being displayed in the table rows myself in the paint() function. So, to display only 8 rows in the table at a time, i increase the font size but from where will QTableView::resizeRowsToContents() get the sizeHint? I guess it will use the default size hint. But i want to specify the size hint myself so that i can control the row height myself.
I'll try using QTableView::resizeRowsToContents() tomorrow when i work on the code.

And the most important question is that why isn't sizeHint() getting called for QTableView? Is it a known issue? I don't think it is mentioned anywhere in the Qt Documentation that sizeHint() doesn't work for QTableView, so i guess it's a bug. Even if it doesn't work, there should be atleast some way to specify the row height in QTableView.

Can you try to run the sample application code i posted and observe the difference in behavior of sizeHint() for QTableView and QListView?

wysota
19th February 2009, 00:35
I guess it will use the default size hint.
It will ask the delegate for the size hint.


And the most important question is that why isn't sizeHint() getting called for QTableView?
Because in the default mode the headers control cell sizes, not the other way round. If you change the resize mode of the headers to ResizeToContents it will ask the contents for the size.


Is it a known issue?
Yes, it's called a feature :)

montylee
19th February 2009, 01:37
aah, you are right! After calling QTableView::resizeRowsToContents() sizeHint() is being called and looks like my problem is resolved :)

I'll test this code in my main application tomorrow.

Thanks!!! looks like once again you rescued me :)

montylee
20th February 2009, 01:18
ok, i am able to set the row height properly now in my main application.
So, this was not a bug i guess. But it should be mentioned in the documentation of sizeHint() that one needs to use set QTableView::resizeRowsToContents() and QTableView::resizeColumnsToContents() to use sizeHint.

wysota
20th February 2009, 08:09
Why should the docs of the delegate contain information about a special behaviour of some other widget? The information you are looking for is there, just not in the place you were looking for it.

See QHeaderView::ResizeMode, especially the last (not counting the one in brackets) sentence from the Interactive value description and first sentence of ResizeToContents value description.

schall_l
11th December 2009, 12:47
Where is resizeRowsToContents() supposed to be called when the model gets updated?

dprust
11th December 2012, 20:10
I know this is resurrecting an old thread, but I wound-up here when trying to figure out why sizeHint wasn't being called when overridden in a custom QGraphicsWidget.
Someone might wind-up here, so I'll add my discovery that having called setContentsMargins at any time before layout will solve this problem.