I find it difficult to translate binary into picture, I use a pixmap.
transfer into the binary is correct but when I show using this program actually does not work.
this is my code:
if (binaryNumber[0]==1)ui->led16->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led16->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[1]=1) ui->led15->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led15->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[2]==1)ui->led14->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led14->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[3]==1)ui->led13->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led13->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[4]==1)ui->led12->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led12->setPixmap(QPixmap("../../picture/ball-gray.png"));
bool ok2 = false;
QByteArray binaryNumber = QByteArray::number(DO.toLongLong(&ok2, 16), 2);
qDebug()<<binaryNumber<<binaryNumber[0]<<binaryNumber[1]<<binaryNumber[2 <<binaryNumber[3];
i.e
binaryNumber =1011
binaryNumber[0] = 1
binaryNumber[1] = 0
binaryNumber[2] = 1
binaryNumber[3] = 1
but when
binaryNumber =100
binaryNumber[0] = 1
binaryNumber[1] = 0
binaryNumber[2] = 0
so when i use a pixmap, then led the flame does not correspond to the binary number because array [0] is different when the size is different.
is there any simple code for me?
Your use of a QByteArray to store bits of a number is unnecessary. In C/C++, you can access the bits directly by doing a bitwise AND (&) with a mask.
template <typename T> static QPixmap setPixmap(T * p, int value, int bitNo)
{
const bool bit = value & (1<<bitNo);
p->setPixmap(bit ? QPixmap("../../picture/ball-yellow.png")
: QPixmap("../../picture/ball-gray.png"));
}
void Class::setDisplay(int val)
{
setPixmap(ui->led12, val, 0);
setPixmap(ui->led13, val, 1);
setPixmap(ui->led14, val, 2);
setPixmap(ui->led15, val, 3);
setPixmap(ui->led16, val, 4);
}
Note that QByteArray::number() returns alphanumeric characters ('0' = 48, '1' = 49 etc.), not characters with the numerical values 0, 1 etc. This is an important difference!
If you do binaryNumber = QByteArray::number(value, 2), this returns a byte array like for example "1010". Thus, binaryNumber[0] == '1', NOT binaryNumber[0] == 1:
if (binaryNumber[0]=='1')ui->led16->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led16->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[1]=='1')ui->led15->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led15->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[2]=='1')ui->led14->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led14->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[3]=='1')ui->led13->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led13->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[4]=='1')ui->led12->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led12->setPixmap(QPixmap("../../picture/ball-gray.png"));
Note that your code is riddled with redundant code lines, resulting in bad quality software. You should try to write the code above in a loop or at least move out the pixmaps. Moving the pixmap initialisations in some static variables or in the constructor of the containing class results in some performance boost, too.
So your class could look similar to this: (I only included the relevant parts, of course, there also has to be the code for the UI stuff.)
class LEDNumberView
{
private:
// member variables:
QPixmap bitOn;
QPixmap bitOff;
// helper function
inline QPixmap getBitPixmap(bool bitVal)
{
return bitVal ? bitOn : bitOff;
}
public:
// constructor
LEDNumberView()
{
QString path = "../../picture/ball-%1.png";
bitOn = QPixmap(path.arg("yellow"));
bitOff = QPixmap(path.arg("gray"));
}
// call whenever you want to change the binary number displayed by the LEDs
void setBinaryNumber(int value)
{
QByteArray binaryNumber = QByteArray::number(value, 2);
ui->led16->setPixmap(getBitPixmap(binaryNumber[0] == '1'));
ui->led15->setPixmap(getBitPixmap(binaryNumber[1] == '1'));
ui->led14->setPixmap(getBitPixmap(binaryNumber[2] == '1'));
ui->led13->setPixmap(getBitPixmap(binaryNumber[3] == '1'));
ui->led12->setPixmap(getBitPixmap(binaryNumber[4] == '1'));
ui->led11->setPixmap(getBitPixmap(binaryNumber[5] == '1'));
}
};
To combine the answer of Kuba Ober with mine, write the setBinaryNumber function as he suggested. It's up to you which method of binary conversion you prefer - bit manipulation (use his method) or convert to and then work with bytes (yours).
Related
I wrote a function to convert a hexa string representation (like x00) of some binary data to the data itself.
How to improve this code?
QByteArray restoreData(const QByteArray &data, const QString prepender = "x")
{
QByteArray restoredData = data;
return QByteArray::fromHex(restoredData.replace(prepender, ""));
}
How to improve this code?
Benchmark before optimizing this. Do not do premature optimization.
Beyond the main point: Why would you like to optimize it?
1) If you are really that concerned about performance where this negligible code from performance point of view matters, you would not use Qt in the first place because Qt is inherently slow compared to a well-optimized framework.
2) If you are not that concerned about performance, then you should keep the readability and maintenance in mind as leading principle, in which case your code is fine.
You have not shown any real world example either why exactly you want to optimize. This feels like an academic question without much pratical use to me. It would be interesting to know more about the motivation.
That being said, several improvement items, which are also optimization, could be done in your code, but then again: it is not done for optimization, but more like logical reasons.
1) Prepender is bad name; it is usually called "prefix" in the English language.
2) You wish to use QChar as opposed to QString for a character.
3) Similarly, for the replacement, you wish to use '' rather than the string'ish "" formula.
4) I would pass classes like that with reference as opposed to value semantics even if it is CoW (implicitly shared).
5) I would not even use an argument here for the prefix since it is always the same, so it does not really fit the definition of variable.
6) It is needless to create an interim variable explicitly.
7) Make the function inline.
Therefore, you would be writing something like this:
QByteArray restoreData(QByteArray data)
{
return QByteArray::fromHex(data.replace('x', ''));
}
Your code has a performance problem because of replace(). Replace itself is not very fast, and creating intermediate QByteArray object slows the code down even more. If you are really concerned about performance, you can copy QByteArray::fromHex implementation from Qt sources and modify it for your needs. Luckily, its implementation is quite self-contained. I only changed / 2 to / 3 and added --i line to skip "x" characters.
QByteArray myFromHex(const QByteArray &hexEncoded)
{
QByteArray res((hexEncoded.size() + 1)/ 3, Qt::Uninitialized);
uchar *result = (uchar *)res.data() + res.size();
bool odd_digit = true;
for (int i = hexEncoded.size() - 1; i >= 0; --i) {
int ch = hexEncoded.at(i);
int tmp;
if (ch >= '0' && ch <= '9')
tmp = ch - '0';
else if (ch >= 'a' && ch <= 'f')
tmp = ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F')
tmp = ch - 'A' + 10;
else
continue;
if (odd_digit) {
--result;
*result = tmp;
odd_digit = false;
} else {
*result |= tmp << 4;
odd_digit = true;
--i;
}
}
res.remove(0, result - (const uchar *)res.constData());
return res;
}
Test:
qDebug() << QByteArray::fromHex("54455354"); // => "TEST"
qDebug() << myFromHex("x54x45x53x54"); // => "TEST"
This code can behave unexpectedly when hexEncoded is malformed (.e.g. "x54x45x5" will be converted to "TU"). You can fix this somehow if it's a problem.
The function gets an integer and a digit, and should return true
if the digit appears an even number of times in the integer, or false if not.
For example:
If digit=1 and num=1125
the function should return true.
If digit=1 and num=1234
the function should return false.
bool isEven(int num, int dig)
{
bool even;
if (num < 10)
even = false;
else
{
even = isEven(num/10,dig);
This is what I've got so far, and I'm stuck...
This is homework so please don't write the answer but hint me and help me get to it by myself.
To set up recursion, you need to figure out two things:
The base case. What is are the easy cases that you can handle outright? For example, can you handle single-digit numbers easily?
The rule(s) that reduce all other cases towards the base case. For example, can you chop off the last digit and somehow transform the solution for the remaning partial number into the solution for the full number?
I can see from your code that you've made some progress on both of these points. However, both are incomplete. For one thing, you are never using the target digit in your code.
The expression num%10 will give you the last digit of a number, which should help.
Your base case is incorrect because a single digit can have an even number of matches (zero is an even number). Your recursive case also needs work because you need to invert the answer for each match.
This funtion isEven() takes a single integer and returns the true if the number of occurence of numberToCheck is even.
You can change the base as well as the numberToCheck which are defined globally.
#include <iostream>
using std::cout;
using std::endl;
// using 10 due to decimal [change it to respective base]
const int base = 10;
const int numberToCheck = 5;
//Checks if the number of occurence of "numberToCheck" are even or odd
bool isEven(int n)
{
if (n == 0)
return 1;
bool hasNumber = false;
int currentDigit = n % base;
n /= base;
if (currentDigit == numberToCheck)
hasNumber = true;
bool flag = isEven(n);
// XOR GATE
return ((!hasNumber) && (flag) || (hasNumber) && (!flag));
};
int main(void)
{
// This is the input to the funtion IsEven()
int n = 51515;
if (isEven(n))
cout << "Even";
else
cout << "Odd";
return 0;
}
Using XOR Logic to integrate all returns
// XOR GATE
return ((!hasNumber) && (flag) || (hasNumber) && (!flag));
Sorry for the vague title.
Currently, if a value is typed into a Q(Double)SpinBox which is out of its range (e.g. typing "100" when max is 90), the value is rejected and instead the last valid value is placed back into the SpinBox.
I want to change this behavior to allow typing out-of-range values which will be automatically corrected (to either the minimum or maximum), because otherwise it would be stupidly hard for the user to guess the value range. After studying the docs and source code of QT, I decided to subclass QSpinBox (will deal with Double variant later) into "QSpinBoxFS", and reimplement both methods mentioned in the title. Somehow though, this is having no effect at all, the behavior is still the same.
These are my methods:
QValidator::State QSpinBoxFS::validate(QString &input,
int &pos)
{
QIntValidator *validator = new QIntValidator();
return validator->validate(input, pos);
}
int QSpinBoxFS::valueFromText(const QString &text)
{
const int max = maximum();
const int min = minimum();
QString copy = text;
int dummy = 0;
QValidator::State state = validate(copy, dummy);
if (state == QValidator::Acceptable)
{
bool ok;
int num = locale().toInt(text, &ok, 10);
if (!ok) { goto bad_text; }
if (num < min) { return min; }
if (num > max) { return max; }
return num;
}
else
{
bad_text:
return (max > 0) ? min : max;
}
}
Of course, this is not really adequate to the pedantic checking done in QSpinBoxPrivate::validateAndInterpret, but I just want the basic concept working for now.
I tried changing validate() to always return Acceptable, but weirdly enough the resulting spinboxes would still behave in the old way.
Either a correction of my own methods or a different approach to this problem are welcome! Thank you for your time.
The signatures of the methods you're trying to reimplement are:
QValidator::State validate(QString & input,int & pos) const # <- const!
int valueFromText(const QString & text) const # <- const!
Both your methods are missing the const, so they are different methods and thus never called from the base class.
On a different note,
QAbstractSpinButton::setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue)
can achieve somehwat similar results (typing values smaller than min will be corrected to min), although you are still prevented from typing values greater than max due to the validator. (And therefor it is insufficient for my needs, just leaving it here for reference.)
can some one help me to rectify this error i have am using VS2010 ASP.Net C#3.0 i found this could on net but it is not working as it give me the error as show in the Screen shot. I am not able to understand the error message
Code reference from http://weblogs.asp.net/abdullaabdelhaq/archive/2009/06/27/displaying-arabic-number.aspx
CODE :
protected void Button1_Click(object sender, System.EventArgs e)
{ //Call Function
this.Label1.Text = "Arabic Number : <b>" + TranslateNumerals(this.TextBox1.Text) + "</b>";
}
public static string TranslateNumerals(string sIn)
{
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decoder = null;
utf8Decoder = enc.GetDecoder();
dynamic sTranslated = new System.Text.StringBuilder();
char[] cTransChar = new char[2];
byte[] bytes = {217,160 };
// Start Converting characters into Arabic mode.
char[] aChars = sIn.ToCharArray();
foreach (char c in aChars)
{
if (char.IsDigit(c))
{
bytes[1] = 160 + Convert.ToInt32(char.GetNumericValue(c));
utf8Decoder.GetChars(bytes, 0, 2, cTransChar, 0);
sTranslated.Append(cTransChar[0]);
}
else
{
sTranslated.Append(c);
}
}
return sTranslated.ToString();
}
The compiler is complaining about your request to implicitly convert the result of the integer addition (160 + Convert.ToInt32...) to a byte. This is a narrowing conversion; integers have a wider range than bytes do, and the compiler wants you to acknowledge, with an explicit cast operator, that you're aware that this could produce runtime errors.
Assuming that adding 160 actually does something useful to a character, I'd advise using something like this instead.
if (c >= '0' && c <= '9')
{
bytes[i] = (byte)((int)c + 160);
}
...which will properly produce, as the i'th value of the array bytes, a byte with a value 160 greater than the char c, if c represents an ASCII digit between 0 and 9.
Don't use the function char.IsDigit, which will return true even if c is a digit outside of the ASCII digit range. I don't run into this much, but since you're explicitly writing multilingual code, you'll want to handle that case.
I haven't reviewed the rest of the post you link to, but given these two quite obvious errors, I wouldn't put much faith in the correctness of the rest of it, frankly.
You could add a cast like (byte) in front of the 160.
I'm a little confused why such a large function is required to do that.
Updated answer:
Given that there are only 10 possible numerals to convert between, you can do something like this to make it slightly more readable. I think, anyway, I don't usually code in c#, and I'm on a mac right now... feel free to bash my code.
public static string TranslateNumerals(string sIn)
{
var sb = new System.Text.StringBuilder();
char[] arabic = { '٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'};
foreach (char c in sIn) {
int idx;
// if it wasn't a number, just append it, otherwise convert it
if(!Integer.tryParse("" + c, idx)) {
sb.Append(c);
} else {
sb.Append(arabic[idx]);
}
}
return sb.toString();
}
// backwards array (which appears frontwards here)
{ '٩','٨','٧','٦','٥','٤','٣', '٢', '١', '٠'};
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();
}
};