PDA

View Full Version : QTableView and display of doubles



b1
12th November 2011, 23:34
G'Day,

I have a QSqlTableModel being displayed in a QTableView and the data comes from an Sqlite database.

The data to be displayed is of type double (valid data is 0.0 to 15.0) and it all displays correctly except when the data ends in ".0". So "13.2" displays as "13.2", "14.5" displays as "14.5" however "15.0" displays as "15", "12.0" displays as "12". When editing the data it displays correctly as I have created my own DoubleSpinBox delegate and set the maximum, minimum, step and decimals to my needs. Editing works, just the displaying prior to editing that is not how I would like it.

I managed to work out how to fix the editing side of it but I am stumped with the display side. I am still getting my head around the model concept.

Any suggestions on where to look, read, or how to go about solving this would be appreciated. Its not a show stopper, I would just like it to look consistent.

Thank you, B1.

poporacer
14th November 2011, 01:02
I am not sure how you are setting the data but you could try something like this:

model->setData(model->index(row,column),QString::number(yourNumber, 'f', 3));

ChrisW67
14th November 2011, 01:09
The model is returning a QVariant double and the default delegate is formatting that with QLocale::toString() using the 'g' format. I would suggest you tackle this with a QStyledItemDelegate attached to the view or just to the double column(s). It need not do much except implement displayText() for double columns.

b1
14th November 2011, 01:35
Thank you poporacer and ChrisW67,

I will try both methods tonight when I get home from work.

Thanks again, B1.

d_stranz
14th November 2011, 18:16
I am not sure how you are setting the data but you could try something like this:

model->setData(model->index(row,column),QString::number(yourNumber, 'f', 3));

If he does this, then the contents of the model in that cell will be a QString and not a double. What "b1" wants to do is to format the display of a double in the table, not to change the underlying model itself. In this case, Chris's method is the correct approach.

b1
16th November 2011, 21:57
Thank you all for the replies. ChrisW67 gave me the solution needed. I had already reimplemented a spinbox for editing so all I had to do was reimplement the drawText function for the displayed text.



void SpinBoxDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
double value = index.model()->data(index, Qt::EditRole).toDouble();
QString str;
painter->drawText(option.rect, str.setNum(value, 'f', 1) );
}



My problem now is when the row is selected the background goes dark blue, as expected, however the text remains black rather than going white, making it impossible to read. Any suggestions to help solve this would be appreciated.

B1.

ChrisW67
16th November 2011, 23:13
If you want custom painting then you have to do the work to honour selections and the like and adjust the colours accordingly. You use the data in the QStyleOptionViewItem to achieve that, e.g:


// something like this
painter->save();
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
painter->setPen(...); // use option.palette.highlightedText()
painter->drawText(...);
}
else {
painter->fillRect(option.rect, option.palette.base());
painter->setPen(...); // use option.palette.text()
painter->drawText(...);
}
painter->restore();

That's why I suggested just overriding QStyledItemDelegate::displayText() to change just the text that the default delegate painting then renders.

b1
18th November 2011, 06:39
Thanks ChrisW67,

I thought I would try the overriding idea and I have failed to get it to work.



QString SpinBoxDelegate::displayText(const QVariant &value, const QLocale &locale) const
{
if (value.userType() == QVariant::Double )
{
return locale.toString(value.toDouble(), 'f', 1);
}
else
{
return QStyledItemDelegate::displayText( value, locale);

}
};


This doesn't compile with this error message:


error: cannot call member function 'virtual QString QStyledItemDelegate::displayText(const QVariant&, const QLocale&) const' without object

I didn't think an object was needed in this case...
All the examples I have found seem to do it this way so any suggestions on where I have gone wrong would be appreciated?

Thanks, B1.

d_stranz
18th November 2011, 18:36
Is your SpinBoxDelegate class derived from QStyledItemDelegate? If it is not, then you can't call a member function for a class that is unrelated to yours. That's what the compiler is trying to tell you: since your class is not derived from QStyledItemDelegate, "this" is not a QStyledItemDelegate, so in order to call one of the QStyledItemDelegate methods, you need an instance of that kind of object.

The solution is simple:


class SpinBoxDelegate : public QStyledItemDelegate
{
// ...
};

Then your displayText() method will compile and work as you expect.

b1
18th November 2011, 23:52
Thank you d_stranz,

You are correct, it was simple and it worked. I couldn't see the wood for the trees!!!

Thank you to all who answered,

B1.