I tried this code but still have problem for QString to short value for example it work well for text = 20 but it return 0 for value = 20.5.
but I need value=20. how can I solve it?
inline __int16 GetStaticToInteger(QLineEdit* lineEdit) {
QString text; __int16 nValue = 0;
nValue = QString::number(lineEdit->text().toDouble()).toShort();
return nValue;
}
'20.5' is not a valid text representation for an integer value. You can check this:
QString str("20.5");
bool ok;
short s = str.toShort(&ok);
qDebug() << ok
The output will be 'false'.
If you need an integer value you can do this:
short s = str.toDouble();
If you need your value rounded to the nearest integer use qRound:
short s = qRound(str.toDouble());
You have made it to complicated.
inline __int16 GetInteger16FromStatic(QLineEdit* lineEdit) {
QString text; __int16 nValue = qRound(lineEdit->text().toDouble());
return nValue;
}
Also Qt provides types with defined size, like qint16 to be compiler/platform independent, so you don't have to use __int16.
Related
In a column in a QTableWidget I want to display some double values. By doing the following, I get my desired display:
double value = 1234.567;
QTableWidgetItem* qti = new QTableWidgetItem(QString::number(value , 'f', 4));
Now, if I enable sorting on the table and sort the values in this column, it will sort as strings. So 90.0000 will come be "larger" than 800.0000 for example (9 > 8).
If I do this instead:
QTableWidgetItem* qti = new QTableWidgetItem();
qti->setData(Qt::DisplayRole, value);
or
QTableWidgetItem* qti = new QTableWidgetItem(QString::number(value , 'f', 4));
qti->setData(Qt::DisplayRole, value);
I can sort my column correctly, but I "lose" the formmating (12.0000 is displayed as 12).
I've also tried like this:
QTableWidgetItem* qti = new QTableWidgetItem();
qti->setData(Qt::UserRole, value);
qti->setData(Qt::DisplayRole, QString::number(value, 'f', 4));
How can I format the display of the values, while still enabling sorting?
(In all code snippets above, the QTableWidgetItems' are added by:
table->setItem(rowNumber, colNumber, qti);
where table is a QTableWidget)
You do it wrong. Let's do it right. The solution is to subclass QTableWidgetItem.
class CustomTableWidgetItem : public QTableWidgetItem
{
public:
CustomTableWidgetItem(const QString txt = QString("0"))
:QTableWidgetItem(txt)
{
}
bool operator <(const QTableWidgetItem& other) const
{
qDebug() << "Sorting numbers";
return text().toFloat() < other.text().toFloat();
// text() is part of QTableWidgetItem, so you can write it as QTableWidgetItem::text().toFloat() as well
}
};
Example insertions
ui->tableWidget->setSortingEnabled(false);
ui->tableWidget->insertRow(0);
ui->tableWidget->setItem(0, 0, new CustomTableWidgetItem(QString::number(90.0005, 'f', 4)));
ui->tableWidget->insertRow(1);
ui->tableWidget->setItem(1, 0, new CustomTableWidgetItem(QString::number(800.0003, 'f', 4)));
ui->tableWidget->insertRow(2);
ui->tableWidget->setItem(2, 0, new CustomTableWidgetItem(QString::number(200.0010, 'f', 4)));
ui->tableWidget->insertRow(3);
ui->tableWidget->setItem(3, 0, new CustomTableWidgetItem(QString::number(200.0020, 'f', 4)));
ui->tableWidget->setSortingEnabled(true);
Sorting behaviour is as expected
ascending
90.0005
200.0010
200.0020
800.0003
descending
800.0003
200.0020
200.0010
90.0005
PS: Remember to turn off sorting before you insert bew items.
Another way of doing this is by using QStyledItemDelegate attached to the double column(s). It need not do much except implement the QStyledItemDelegate::displayText() function.
For further details, see QTableView and display of doubles at Qt Centre.
Here's what I came up with, based on Mangesh's answer, for a similar problem displaying a percentage:
class percentageItemC : public QStyledItemDelegate
{
QString displayText(const QVariant &value, const QLocale &locale) const
{
return QString::asprintf("%0.3lf%% ", value.toDouble());
}
} percentageItem;
That's any number of digits to the left of the decimal, 3 to the right, and a long float with a percent sign. Then, do a
ui->twMyTable->setItemDelegateForColumn(1, &percentageItem);
in yer form's class. I can also re-use them for other columns, and presumably rows.
This method doesn't slow things down with extra text to float conversions. You can also have nice extras, like commas, percent signs and currency signs in it. I have this for currency:
class currencyItemC : public QStyledItemDelegate
{
QString displayText(const QVariant &value, const QLocale &locale) const
{
return locale.toCurrencyString(value.toDouble()) + " ";
}
} currencyItem;
I use:
QTableWidgetItem *item = new QTableWidgetItem();
item->setData(Qt::EditRole, number);
to create the table items. It is smart about these: it creates a QVariant, and then sorts based on the type. This way, you don't have to set the underlying data to a string, but it can be any type it has a sort for.
The columns sort numerically like they're s'posed to, but they display in any format ya like. ;}
From my point of view the best option to solve this problem is to create new class with usage of setData() with Qt::UserRole to store unformatted data. In this setup you can store real data and text together. This has more memory consumption but you doesn't need to convert from string to int/float/etc.
I've tested many other roles Qt::EditRole, Qt::DisplayRole, etc and they are overwriting stored data/text and you can't store both values.
Here is my final solution of class displaying % percent values (python code)
from PyQt5 import QtWidgets, QtCore
class PercentTableWidgetItem(QtWidgets.QTableWidgetItem):
# Float value
value: float = 0
def __init__(self,
value: float = 0
):
''' Constructor.'''
super().__init__()
# Set variables
self.value = value
# Set item data
self.setData(QtCore.Qt.UserRole, value)
self.setText(f'{self.value:.2f}%')
def __lt__(self, other: QtWidgets.QTableWidgetItem):
''' Operation < for sorting.'''
value = other.data(QtCore.Qt.UserRole)
return (value is not None) and (self.value < value)
Usage in code as simple as below
table = QTableWidget()
table.setItem(0,0,PercentTableWidgetItem(35.67))
I have the same code in 2 different projects. The Qstring::number(data.toLong(&ok,2),16) works in one project and in the other project it does not work. Does anyone know what the reason could be? The code is as follows
1) unsigned short status;
2) long int setting;
3) bool ok;
4) QString data_selected;
5) data_selected = lineEdit_data->text(); //get the binary value
6) data_selected = QString::number(data_selected.toLong(&ok, 2), 16); //convert binary value to hex value
7) setting = data_selected.toLong(&ok, 16); //convert string to integer
In line 5 I am getting data from a lineEdit. This line works fine. I just inserted a new text edit box and displayed the data there and there I can see data. I have data as "1000000000001000". Then I execute line 6, the output of which is '8008' in first case and '0' in the other project. This is the problem. The code is exactly the same. I have copied and pasted. But in debugging I can see this difference. Please can anyone tell me why this is happening?
I thought that comment under answer was clear.
Correct code like this to detect what is the problem:
ulong setting;
bool ok;
data_selected = data_selected.trimmed(); // first try without this line
ulong value = data_selected.toULong(&ok, 2);
if (ok) {
data_selected = QString::number(value, 16);
setting = data_selected.toULong(&ok, 16);
} else {
data_selected = "convertion error";
}
How get int code of qchar in this table http://www.ascii-codes.com/cp866.html ?
Here is my code:
int getCp866Code(QChar c) {
if (!c.isSurrogate()) {
QString temp = c;
QTextCodec* cp866 = QTextCodec::codecForName("IBM 866");
QByteArray byteArray = cp866->fromUnicode(temp);
return (int) byteArray[0];
}
return -1;
}
getCp866Code('ж') // returns -90, not 166
The question is ill posed. QChar is a UTF-16 code unit (which also means it can be part of a surrogate pair). Your best shot would be
Check that it's not part of a surrogate pair (QChar::isSurrogate)
Build a QString consisting only of that char, then use QTextCodec to encode the string in CP866. Then extract the first byte of it.
Note that it's unspecified what you get if your code point is not encodeable in CP866.
I am newbie in QT(4.7.4) and I am search for function, that checks an QString for alpha-characters and returns "true" if in this QString contains only characters.
Should I write this simple function myself? :( I hope it exists such function as isText() in VBA, but in Google and documentation I have not found it.
Thanks for answers and sorry for my english :)
You can simply validate the string with a QRegExp class matching an alphanumeric string. I suggest to use it with QValidator to be more clear.
You could use something like this (If your goal is to accept only strings, which contains a single character):
bool containsOnly(QString str, QChar c)
{
for(int i=0; i<str.length(); i++)
if(str.at(i)!=c)
return false;
return true;
}
and in use:
bool b = containsOnly("String", 'a');
I have a QTableWidget and the first column contains numbers from 1 to 1000. Now I need to sort the table based on this first column.
I'm using the function sortItems(int column, Qt::AscendingOrder), but it is displayed as:
1, 10, 100, 1000, 101, 102, ...
Yet I need this result:
1, 2, 3 ,4...., 1000.
I'm using a CSV file for populating the table.
The values are sorted as strings because you stored them as such in the model.
The QVariant can remember the original type of the data if you let it do the conversion itself, and the comparison operator from that type will be used when sorting:
// Get the value from the CSV file as a numeric type
int valueFromCsvFile = ...;
// don't do this
QTableWidgetItem *item = new QTableWidgetItem(QString::number(valueFromCsvFile));
// but do this instead
QTableWidgetItem *item = new QTableWidgetItem;
item.setData(Qt::EditRole, valueFromCsvFile);
The cell editor will also adapt to the type of the QVariant:
QSpinBox for int,
QDoubleSpinBox for double and float,
QDateTimeEdit for QDateTime
...
The easiest way is probably to subclass QTableWidgetItem and then implement the < operator to be smart about the fact that you're sorting numbers and not strings.
class MyTableWidgetItem : public QTableWidgetItem {
public:
bool operator <(const QTableWidgetItem &other) const
{
return text().toInt() < other.text().toInt();
}
};
Then when you're populating your table you can pass it instances of your custom items that know how to sort themselves properly instead of the generic ones.
One way that worked in my situation was
1) before filling the table, turn off sorting:
table.setSortingEnabled(False)
2) pad the number strings with blanks and make all strings in the column have the same length:
(' '+numStr)[-4:]
3) after filling the table, turn on sorting:
table.setSortingEnabled(True)
This fixed the row sorting problem and the numerical order.
I don't know if the accepted answer used to work, but with Qt5.1, it doesn't.
In order to work, the operator< definition has to match the virtual definition from qtablewidget.h.
Another interesting addition is to sort items that have numbers, but start with a currency sign ($ or € for instance) or end with %.
Here is the updated code:
class TableNumberItem : public QTableWidgetItem
{
public:
TableNumberItem(const QString txt = QString("0"))
:QTableWidgetItem(txt)
{
}
bool operator < (const QTableWidgetItem &other) const
{
QString str1 = text();
QString str2 = other.text();
if (str1[0] == '$' || str1[0] == '€') {
str1.remove(0, 1);
str2.remove(0, 1); // we assume both items have the same format
}
if (str1[str1.length() - 1] == '%') {
str1.chop(1);
str2.chop(1); // this works for "N%" and for "N %" formatted strings
}
double f1 = str1.toDouble();
double f2 = str2.toDouble();
return str1.toDouble() < str2.toDouble();
}
};
Then, you add the items that contain numbers using something like this:
myTableWidget->setItem(row, col, new TableNumberItem("$0"));
Note that this class must be used with numbers only, it will not sort strings correctly (as is also the case with the accepted answer).
I had same problem and the The answer of #Chris worked for me!
but a little modification is need. I can't comment. so I write here.
class MyTableWidgetItem : public QTableWidgetItem {
public:
bool operator <(const QTableWidgetItem &other) const
{
if (text()=="")
return text().toDouble() > other.text().toDouble();
else
return text().toDouble() < other.text().toDouble();
}
};