Solved How to prevent exponential numbers view in tableView?
-
Hi,
I have tableView and need to show big numbers in it like 1 million which is more than 6 digit. But unforunatelly it's shown like attached picture?!
How can I show it normal?!...
Regards,
Mucip:) -
@Mucip
what type of model are you using? standard item model or custom model?
Also whats the type of the corresponding column data? -
Hi @raven-worx ,
The number comes from PostgreSQL as numeric which is double...
For SQL Query: QSqlQueryModel
For tableView: QTableViewRegards,
Mucip:) -
@Mucip
ok so then you could try to cast the column already in the SQL query.
Or subclass your sql model and in data() (for the corresponding column'sQt::DisplayRole
) return:QString::number(doubleVal, 'f', 0)
-
@Mucip
you can use a delegate override to return a correct string to the view.
Take a look at this old forum post, it will give you an idea of how it can be implemented:
https://forum.qt.io/topic/35577/formatting-numbers-in-qtableview-solved/4 -
Hi @raven-worx ,
My code is like below:QSqlQueryModel *modelTableDinamoStok; this->modelTableDinamoStok = new QSqlQueryModel(this); modelTableDinamoStok->setQuery("SELECT stok_kod, stok_ad, stok_birim FROM stok_kart WHERE stok_tip = 'HAMMADDE' OR stok_tip = 'HAZIRMALZEME' ORDER BY stok_kod;", baglanti::mdb() ); ui->tVStok->setModel(modelTableDinamoStok);
Regards,
Mucip:) -
Hi @KillerSmath ,
I already use delegate in other forms. But this number comes directly from sql query?!...Regards,
Mucip:) -
Hi @KillerSmath ,
I think same problem.
Yes, I will check this... ;-)Regards,
Mucip:) -
@Mucip
The delegate uses QLocale to convert it to String, and by default, it uses 'g' format to convert float and double values to string.Edit: If you're little curious, you can see this conversion directly in the QAbstractItemDelegate source code (Inherited By QItemDelegate, the standard QTableView delegate)
-
Please excuse me for having my say, but this area has ben a bug-bear of mine for some time.
I'm sure that @KillerSmath, the post he links to and the others who do this via a delegate know much more than I do about Qt. But to me this is just the wrong place to do number formatting. For one, thing it locks all the logic down into some
QStyledItemDelegate
. But the string formatting of the number, to me, is just not something to do with a table's/delegate'sdisplayText()
. You may want it for all sorts of other purposes, e.g. exporting the data. Shouldn't a delegate be used for drawing it big, or upside-down or with purple stripes in a box?Surely @raven-worx's very, very simple code in
data(Qt::DisplayRole)
is the place that makes logical sense for this feature, returning the desired string representation to be used for display while still being available to be called by anything else which wants it, and that's where I have done mine. It also has the virtue of being about one line of code instead of all the code required for aNumberFormatDelegate
-type solution! -
Hi @raven-worx ,
Well, How can I cast it in SQL?Regards,
Mucip:) -
Hi @raven-worx ,
I appllied CAST as follow:modelTableTalep->setQuery("select sn, stok_kod, stok_ad, CAST(talep_adet AS TEXT), talep_birim, mevcut_stok, talep_onay, sebep, talep_zaman, termin_tarih, kullanici, talep_eden FROM talep ORDER BY sn DESC;",baglanti::mdb());
But still same problem 1,2E+8 like?!...But I wanted to use "Qt::DisplayRole"
Any example please?...regards,
Mucip:) -
@Mucip
If you are saying that your column is theCAST(talep_adet AS TEXT)
and that still comes out as1,2E+8
, then that would mean that is the textual representation of that number up at SQL. Depending on your SQL server, something likeCONVERT(talep_ad, ???)
would be required, where the???
is whatever your SQL allows for producing a number in digits instead, assuming there is such a parameter.As for doing it in your model override's
data()
function (which is how I would do it), you could actually look at the docs. You want something like:QVariant MyModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const { val = QSqlQueryModel::data(index, role); if (role == Qt::DisplayRole && index.column() == aDoubleNumberColumn) { doubleVal = static_cast<double>(val.value()); return QString::number(doubleVal, 'f', 0) } return val; }
-
Hi @JonB ,
In this way I neet to change row by row?! Am I wrong?!...Regards,
Mucip:) -
@JonB Strongly disagree with your post.
The model should be pure data. If it contains a
double
then the model only has to care about those 64bits of data. It does not have to care about how to represent that data to the user, it's not its job. The delegate is the one that is concerned to converting pure data into something the user can read/interact with.Surely @raven-worx's very, very simple code in data(Qt::DisplayRole) is the place that makes logical sense for this feature
This is even worse as it breaks the logic of the model itself. Try sorting the column containing the numbers converted to string using
QSortFilterProxyModel
and you'll quickly realised how bad it is to make the model care about visual representation of data.The solution proposed by @KillerSmath is the correct one and the only acceptable one from a model-view logic point of view.
class NumberFormatDelegate : public QStyledItemDelegate{ Q_OBJECT Q_DISABLE_COPY(NumberFormatDelegate) public: NumberFormatDelegate(QObject *parent = Q_NULLPTR) :QStyledItemDelegate(parent) {} QString displayText(const QVariant &value, const QLocale &locale) const Q_DECL_OVERRIDE{ switch(value.type()){ case QMetaType::Float: return locale.toString(value.toFloat(),'f'); case QMetaType::Double: return locale.toString(value.toDouble(),'f'); default: return QStyledItemDelegate::displayText(value,locale); } } };
ui->tVStok->setItemDelegateForColumn(3, new NumberFormatDelegate(this));
-
Dear @VRonin ,
I uset ItemDelegate and perfect result. Thanks all...Regards,
Mucip:) -
@VRonin
Well, just to say I equally strongly disagree with yours :) Of course I respect your doubtless expert views too! I trust we can still be friends.There is a reason that the
data()
method has a role ofDisplayRole
. Docs:The key data to be rendered in the form of text. (QString)
That's precisely what I want to use. Otherwise remove it, and say there is no such role for the data. I absolutely do allow sorting of my data. And of course the whole point is that I do not sort by
DisplayRole
, I sort byEditRole
(orSortRole
).If I sit down one day and have a column in my model which is, say, an int like an enumerated which I want displayed as
apples
,pears
,oranges
, and I decide I do want my users to be able to sort by the string they see, I have the option of sorting byDisplayRole
if that is what I intend. I can't if it's buried away in some styled item delegate.Meanwhile, I do not only use the data in the model for display in views/tables. I might, for example wish to use to export textual data from my model. And I want the same text whether it's a cell in a table or an item in a PDF file. So again, I don't want the logic to be in some styled item delegate. The textual format of a number, commas, negative signs, leading currency symbol etc. is a real attribute of the data, not just a whim of a table view. To me.
-
@JonB said in How to prevent exponential numbers view in tableView?:
The key data to be rendered in the form of text
data to be rendered the model doesn't care about actual rendering it provides the data to be rendered by someone else
And of course the whole point is that I do not sort by DisplayRole, I sort by EditRole
EditRole
andDispalyRole
have another purpose. The easiest comparison is with excel/libreoffice calc:EditRole
contains the formula of a cell,DispalyRole
contains the result of that formula. The formula does not need to be rendered hence it is buried in that role while the result (not his graphical representation, just the data of the result) is stored inDispalyRole
. Then there's the practical point of all the models provided by Qt implementEditRole
andDispalyRole
as one and the same.I might, for example wish to use to export textual data from my model. And I want the same text whether it's a cell in a table or an item in a PDF file
Nothing stops you from storing suggestions on how to render the data inside other roles. There are even pre built roles for fonts and colours, so you can store even the number formatting you prefer in a user role to be used by whoever will take care of rendering that data but the model should only care about data, never of its representation
-
@VRonin
So it's OK forForegroundRole
to return the color to display text in a table but it's not OK forDisplayRole
to return the desired text to be displayed there? The text should be done in a delegate instead, so why shouldn't the color be done in one too? You treatDisplayRole
very differently from other roles such asForegroundRole
, and I certainly did not get that as I learned Qt, I don't see from the docs where I should understand this very special handling ofDisplayRole
.I wish you had been there when I started out on this! [What's your phone number, we should talk so I can understand? ;-) ] Anyway, I am where I am now, and am committed to the way I have implemented in my code. Next time, when I don't start out from existing 32K of already (badly) written code, I will go down the delegate route!
-
@JonB said in How to prevent exponential numbers view in tableView?:
So it's OK for ForegroundRole to return the color to display text
Indeed. It tells the guy who actually needs to render the item what color to use but it's pure data it doesn't take ownership of the painting. The delegate is free to ignore that role when rendering if it doesn't fit the representation it is showing to the user
so why shouldn't the color be done in one too?
it is indeed done in the delegate.
I don't see from the docs where I should understand this very special handling of DisplayRole
And there isn't. [slight simplification ahead]
ForegroundRole
contains 4 integers for argb. it's pure data as wellbut it's not OK for DisplayRole to return the desired text to be displayed there?
Yep, as it hides from the delegate the fact that it should render a decimal number, the delegate will just see a string and it might render it in the wrong way.