Home
About
How to ask about Qt Widgets programming problems — Example 2
Asking about fixing code that’s not compiling or behaving correctly
must be as minimal as possible, and it has to demonstrate the issue.
Why?
Because, of two main reasons:
- The help will come from other real people.
You are seeking help from other developers, volunteers, meaning they are doing it for free.
They have their own lives, joys and sorrows, messy code, and annoying colleagues to deal with.
So, minimizing your code effectively, is a way to say thank you, show respect for their time and energy, and to show appreciation for their willingness to provide the free assistance.
- It’s for your own good.
Learning how to dissect the project, extract just the problematic bits, and make a working example out of them, is an essential skill in this specialty.
The best way to acquire it, is by learning how to ask. Put yourself in the receiver’s shoes, and see if what you’re telling them is as ready as possible for them to start working on using their machines. That does not necessitate expertise; all you have to do, is to make sure other people can see the same thing you see when you run the program.
In this series, I am using random questions I find on the internet, and transform them to what they should have been. This creates a collection of practical examples to learn from.
This is Qt Widgets Minimal Example Template (unless you have to use Qt Designer):
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
return a.exec();
}
Question of the day:
It says:
At qDebug() << gradient;
, it outputs:
QBrush(QColor(Invalid),LinearGradientPattern)
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
QLinearGradient gradient;
QString gradientString = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(15, 21, 255, 155), stop:1 rgba(126, 22, 224, 155));";
QWidget* widget = new QWidget;
widget->setStyleSheet(gradientString);
widget->setWindowTitle("StyleSheet");
widget->show();
// Parse the string to create a QLinearGradient
// Remove the "qlineargradient(" and ")" parts
gradientString.replace("background-color: qlineargradient(", "");
gradientString.chop(2);
// Extract the start and end points
QRegularExpression rx("x1:([\\d.]+), y1:([\\d.]+), x2:([\\d.]+), y2:([\\d.]+)");
QRegularExpressionMatch match = rx.match(gradientString);
if (match.hasMatch())
{
float x1 = match.captured(1).toFloat();
float y1 = match.captured(2).toFloat();
float x2 = match.captured(3).toFloat();
float y2 = match.captured(4).toFloat();
qDebug() << "x1:" << x1 << "y1:" << y1 << "\nx2:" << x2 << "y2:" << y2 << "\n";
gradient = QLinearGradient(QPointF(x1, y1), QPointF(x2, y2));
// Extract the color stops
QRegularExpression rxStop("stop:([\\d.]+) rgba\\((\\d+), (\\d+), (\\d+), (\\d+)\\)");
int pos = 0;
while ((match = rxStop.match(gradientString, pos)).hasMatch())
{
float stop = match.captured(1).toFloat();
int r = match.captured(2).toInt();
int g = match.captured(3).toInt();
int b = match.captured(4).toInt();
int a = match.captured(5).toInt();
qDebug().nospace() << "stop: " << stop << " rgba(" << r << "," << g << "," << b << "," << a << ")\n";
// Check if the color values are valid
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 255)
gradient.setColorAt(stop, QColor(r, g, b, a));
else
qDebug() << "Invalid color values";
pos = match.capturedEnd();
}
qDebug() << gradient;
}
widget = new QWidget;
QPalette palette;
palette.setBrush(widget->backgroundRole(), QBrush(gradient));
widget->setPalette(palette);
widget->setWindowTitle("Palette");
widget->show();
return app.exec();
}
What’s wrong in the way I’m creating the QLinearGradient
?
If we run this, it outputs:
x1: 0 y1: 0
x2: 1 y2: 0
stop: 0 rgba(15,21,255,155)
stop: 1 rgba(126,22,224,155)
QBrush(QColor(Invalid),LinearGradientPattern)
So it seems the regexes work correctly, meaning the issue is not there, so why are we including them in what’s supposed to be a minimal example?
Let’s remove them, and instead, use
hard-coded values, the ones from the output:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString gradientString = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(15, 21, 255, 155), stop:1 rgba(126, 22, 224, 155));";
QWidget* widget = new QWidget;
widget->setStyleSheet(gradientString);
widget->setWindowTitle("StyleSheet");
widget->show();
//the first 2 lines of the output
QLinearGradient gradient(QPointF(0, 0), QPointF(1, 0));
//lines 3-4 of the output
gradient.setColorAt(0, QColor(15,21,255,155));
gradient.setColorAt(1, QColor(126,22,224,155));
qDebug() << gradient;
widget = new QWidget;
QPalette palette;
palette.setBrush(widget->backgroundRole(), QBrush(gradient));
widget->setPalette(palette);
widget->setWindowTitle("Palette");
widget->show();
return a.exec();
}
This outputs the last line of the previous output, meaning we trimmed a big chunk, which was just cluttering the real problem.
Can we trim this even further? Yes, absolutely:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//I prefer using stack-allocated objects when making minimal examples
//they take care of themselves.
QWidget styleSheetWidget;
styleSheetWidget.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 darkRed, stop:1 darkBlue);");
styleSheetWidget.setWindowTitle("StyleSheet");
styleSheetWidget.show();
QLinearGradient gradient(QPointF(0, 0), QPointF(1, 0));
gradient.setColorAt(0, Qt::darkRed);
gradient.setColorAt(1, Qt::darkBlue);
qDebug() << gradient;
QWidget paletteWidget;
QPalette palette;
palette.setBrush(paletteWidget.backgroundRole(), QBrush(gradient));
paletteWidget.setPalette(palette);
paletteWidget.setWindowTitle("Palette");
paletteWidget.show();
return a.exec();
}
Now, that is minimal and clean.