Losing style when adding specificity to a Qt stylesheet - c++

Here's my code:
const QString STYLE_SHEET = "background-color: rgba(x,x,x,y);"
"border: 1px solid gray;"
"border-radius: 0px;"
"border-top: 1px solid red;"
"border-bottom: 1px solid blue;"
"border-radius: 0px;";
The SS is applied later in the code like this:
QWidget * myWidget;
myWidget = new QWidget(parent);
myWidget.setObjectName("myWidgetName");
myWidget.setStyleSheet(STYLE_SHEET);
It works like a champ except that the borders bleed into a child QFrame. If I add specificity to STYLE_SHEET by bracketing it with the following:
const QString QWidget#myWidgetName { }
The STYLE_SHEET ceases to apply. It solves the bleed down to the child QFrame but my QWidget loses its style. And what good is a QWidget without style?

const QString STYLE_SHEET = "QWidget#myWidgetName {\n"
" background-color: rgba(x,x,x,y);\n"
" border: 1px solid gray;\n"
" border-radius: 0px;\n"
" border-top: 1px solid red;\n"
" border-bottom: 1px solid blue;\n"
" border-radius: 0px;\n"
"}\n";

Related

Change color of frame of the QGroupBox when hover on it

I have the next code where I want to change color of the frame from silver to red when hover on the frame by mouse:
#include <QApplication>
#include <QGroupBox>
#include <QLineEdit>
#include <QVBoxLayout>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QWidget* mainWidget = new QWidget;
mainWidget->resize(600, 400);
QVBoxLayout* mainLayout = new QVBoxLayout(mainWidget);
QLineEdit* lineEdit = new QLineEdit("initial text");
lineEdit->setStyleSheet(
"QLineEdit"
"{"
" font-size: 14px;"
"}"
//
);
QGroupBox* groupBox = new QGroupBox("Group Box Title");
groupBox->setStyleSheet(
"QGroupBox {"
" font: bold;"
" font-size: 10px;"
" border: 1px solid silver;"
" border-radius: 6px;"
" margin-top: 12px;"
" margin-left: 10px;"
"}"
// "QGroupBox:hover" // don't work as expected
// "{"
// " border: 1px solid red;"
// "}"
"QGroupBox:focus"
"{"
" border: 1px solid red;"
"}"
"QGroupBox::title"
"{"
" subcontrol-origin: margin;"
" left: 16px;"
" padding: 5px 8px 0px 8px;"
"}"
//
);
groupBox->setFocusProxy(lineEdit);
groupBox->setLayout(new QVBoxLayout);
groupBox->layout()->addWidget(lineEdit);
mainLayout->addWidget(groupBox);
mainWidget->setFocusPolicy(Qt::ClickFocus);
mainWidget->show();
return app.exec();
}
Eventually I decided at least implement changing color of the frame when it in the focus, and focus changing by clicking.
But I want to change color by hovering.
I have tried "QGroupBox:hover{}" and "QGroupBox:enabled:hover {}" - both of them don't give diserable effect.
Can anyone tell me what am I doing wrong?

Unable to set stylesheet properties using qss file

I am trying to set some styles to all the QLineEdits in my application. Following is the code:
QLineEdit {
border: none;
padding-bottom: 2px;
border-bottom: 1px solid black;
color: #000000;
background-color:rgba(0,0,0,0);
}
QLineEdit:focus{
border: 0px solid white;
border-bottom: 2px solid #2196F3;
color: #000000;
}
When I input this style using the GUI i.e by setting the stylesheet option in form editor for each individual lineEdit, it works.
However when I try to add the same code using a qss file in resources, it doesn't work. I use the following code for applying stylesheet:
#include "mainwindow.h"
#include <QApplication>
#include <QFile>
#include <conio.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// QFile styleFile( ":/Stylesheets/QLineEdit.qss" );
// styleFile.open( QFile::ReadOnly );
// std::printf("hi0");
// // Apply the loaded stylesheet
// QString style( styleFile.readAll() );
// a.setStyleSheet( style );
QFile file(":/Stylesheets/QLineEdit.qss");
file.open(QFile::ReadOnly);
QString styleSheet = QLatin1String(file.readAll());
a.setStyleSheet(styleSheet);
MainWindow w;
w.show();
return a.exec();
}
What could be the problem here?
Edit: Adding code for the QPushButton:
QPushButton, QPushButton:focus {
background-color:#2196F3;
border: none;
color: white;
padding: 3px 20px;
}
QPushButton:hover, QPushButton:hover:focus {
background-color: #1976D2;
border-color: #ffffff;
}
QPushButton:pressed,
QPushButton:pressed:focus {
background-color: #388E3C;
border: none;
color: white;
}
QPushButton:disabled {
color: #cccccc;
background-color: #cccccc;
border: none;
}
Let's summarize the outcome of the discussion.
Replace the file.open(QFile::ReadOnly); with file.open(QFile::ReadOnly | QFile::Text); QFile::Text is important, because:
The QIODevice::Text flag passed to open() tells Qt to convert
Windows-style line terminators ("\r\n") into C++-style terminators
("\n"). By default, QFile assumes binary, i.e. it doesn't perform any
conversion on the bytes stored in the file.
Furthermore, when setting the stylesheet globally, there are some specifics which should be taken into account:
A stylesheet affects the widget and everything below it in the widget's hierarchy. If set for a widget explicitly (from the code or using the form editor) the parents of the widget are not affected, as if it were set for the whole application. E.g. if you set the following: QWidget { background-color: red; } for a particular widget, this widget and all of its children will have a red background. If you set the same stylesheet from the qss file for the whole application, all the widgets will have a red background. So a great deal of care should be taken about the inheritance between the widgets. Using the right selector types is then crucial.

Qt stylesheet for all QProgressBars programmatically (C++)

Having trouble understanding how to programmatically set a stylesheet to be applied on several (or even all) widgets in Qt Creator 4.1 (Qt 5.7) with C++.
For example, say I have 3 progress bar widgets; I have explicitly set each with the same stylesheet with css like so:
ui->c1->setStyleSheet("QProgressBar {"
"background-color: #74c8ff;"
"color: #0a9dff;"
"border-style: outset;"
"border-width: 2px;"
"border-color: #74c8ff;"
"border-radius: 7px;"
"text-align: left; }"
"QProgressBar::chunk {"
"background-color: #010327; }");
ui->c2->setStyleSheet("QProgressBar {"
"background-color: #74c8ff;"
"color: #0a9dff;"
"border-style: outset;"
"border-width: 2px;"
"border-color: #74c8ff;"
"border-radius: 7px;"
"text-align: left; }"
"QProgressBar::chunk {"
"background-color: #010327; }");
ui->c3->setStyleSheet("QProgressBar {"
"background-color: #74c8ff;"
"color: #0a9dff;"
"border-style: outset;"
"border-width: 2px;"
"border-color: #74c8ff;"
"border-radius: 7px;"
"text-align: left; }"
"QProgressBar::chunk {"
"background-color: #010327; }");
I would like to use the Qt Stylesheets to create a stylesheet for my widgets and avoid all this code suplication.
After reading the docs, the syntax would be like this :
QProgressBar
{
background: #74c8ff;
color: #0a9dff;
border-style: outset;
border-width: 2px;
border-color: #74c8ff;
border-radius: 7px;
text-align: left;
}
QProgressBar::chunk
{
background-color: #010327;
}
but, apparently you cannot copy the parameter names as used in a setStylesheet with css directly to a syntax like the one above.
I also tried something like this
QProgressBar.setStyleSheet("QProgressBar {"
"background-color: #74c8ff;"
"color: #0a9dff;"
"border-style: outset;"
"border-width: 2px;"
"border-color: #74c8ff;"
"border-radius: 7px;"
"text-align: left; }"
"QProgressBar::chunk {"
"background-color: #010327; }");
None of the above worked (undeclared identifiers and syntax errors).
Could someone provide an example of how you can achieve defining a single stylesheet with the above parameters to be applied for all widgets? If you could point to a resource (I could not find anything!) that explains the available parameters to achive my goal, that would be as good).
Finally, if such a stylesheet is created for all progress bars, how can I exclude one progress bar (or any widget for that matter) from having that stylesheet and have instead a different one?
Use qApp->setStyleSheet instead of QProgressBar.setStyleSheet to set stylesheet for all widgets in your application. More examples here: http://doc.qt.io/qt-5/stylesheet-examples.html

How to adjust a QSlider's handle?

I'm writing an app for a touchscreen, and the default handle is too small to grab reliably, so I want to make it bigger. According to the official documentation, several answers on SE, and a couple of other forums, this ought to work in a QWidget's constructor:
sliderGrandMaster = new QSlider(Qt::Vertical, panelRight);
sliderGrandMaster->setGeometry( appdata->buttonBorder , //Left
buttonTopRight + appdata->buttonBorder , //Top
halfwidth - (2 * appdata->buttonBorder), //Width
buttonRemainingHeight - (2 * appdata->buttonBorder)); //Height
sliderGrandMaster->setRange(0, RANGE_MAX);
sliderGrandMaster->setTickInterval(RANGE_MAX / 10);
sliderGrandMaster->setTickPosition(QSlider::TicksBothSides);
QString temp = QString("handle:vertical { background: green; height: %1px; margin: 0 -%2px; }")
.arg(buttonRemainingHeight / 5)
.arg(halfwidth / 3);
sliderGrandMaster->setStyleSheet(temp);
But it seems to have no effect. The handle is the same small size regardless of what values I put in the stylesheet, and it's not even green.
With my values at runtime, temp ends up being handle:vertical { background: green; height: 66px; margin: 0 -32px; }. The size of the slider is 94px wide by 331px tall.
Am I missing something?
Edit:
This:
QString temp = QString("QSlider::handle { background: green; height: %1px; width: %1px; margin: 0 -%2px; }")
.arg(buttonRemainingHeight / 5)
.arg(halfwidth / 3);
sliderGrandMaster->setStyleSheet(temp);
at least got it green. But the size is still wrong. Qt version 5.4.2
You can change the size of the handle just with a simple stylesheet. Example :
Is done with the following stylesheet :
QSlider::groove:horizontal
{
border:none;
margin-top: 10px;
margin-bottom: 10px;
height: 10px;
}
QSlider::sub-page
{
background: rgb(164, 192, 2);
}
QSlider::add-page
{
background: rgb(70, 70, 70);
}
QSlider::handle
{
background: white;
border: 3px solid black;
width: 60px; // **Change the width here**
margin: -30px 0;
}
Ok, using Qt 5.6.1 I got some progress on this. The following code
QSlider* slider = new QSlider(this);
slider->setOrientation(Qt::Horizontal);
slider->setStyleSheet("QSlider::groove:horizontal { "
"border: 1px solid #999999; "
"height: 20px; "
"background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4); "
"margin: 2px 0; "
"} "
"QSlider::handle:horizontal { "
"background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f); "
"border: 1px solid #5c5c5c; "
"width: 30px; "
"margin: -2px 0px; "
"} ");
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(slider);
layout->addWidget(new QSlider(Qt::Horizontal, this));
setLayout(layout);
may be placed into an emty QWidget to work. It simply adds two QSliders, one of which is modified using a style sheet.
As you may see, I used to change the groove too and it is working as intended. But there are strange issues which could be a bug at all. Try commenting out some properties of the groove style sheet, like border, background and margin. If there are no effective properties, the width property of the handle is dropped. As I cannot find any constraint in the documentation, I wonder why this happens.
Also note the issues drawing the border around the handle. Seems to need some more fine tuning. ;)
Summing things up the quick solution for you should be added some default properties for the groove.

How to break a long line in double quotes?

For instance, in my C++ code:
setStyleSheet
(
"QPushButton{background-color:#9dce2c; border-radius:7px; border:1px solid #83c41a; color:#000000; font-size:15px; font-weight:bold; padding:4px 24px; text-decoration:none; }"
"QPushButton:pressed { border:2px; solid black; }"
"QPushButton:hover { background-color:grey; }"
"QPushButton:focus { outline: none; }"
"QGroupBox { font-size:15px; font-weight:bold; padding:6px 0px; text-decoration:underline; }"
);
Any ideas?
C and C++ automatically concatenate adjacent string literals, so you can just do
setStyleSheet
(
"QPushButton{background-color:#9dce2c; border-radius:7px;"
" border:1px solid #83c41a; color:#000000; font-size:15px;"
" font-weight:bold; padding:4px 24px; text-decoration:none; }"
// ...
);
and it will work as intended. (The indentation is not necessary here, but I think it would be good style to indicate that the second and third lines here are intended to be continuations of the first.)
Brian's got the right idea (indeed - you were already using this technique, with all the long lines being concatenated), but if you want there to be one space after each semi-colon, you'll need to move the quotes correspondingly....
setStyleSheet
(
"QPushButton{background-color:#9dce2c; border-radius:7px; "
"border:1px solid #83c41a; color:#000000; font-size:15px; "
"font-weight:bold; padding:4px 24px; text-decoration:none; }"
"QPushButton:pressed { border:2px; solid black; }"
"QPushButton:hover { background-color:grey; }"
"QPushButton:focus { outline: none; }"
"QGroupBox { font-size:15px; font-weight:bold; padding:6px 0px; "
"text-decoration:underline; }"
);
(You can end lines with \n" to inject newlines if you want the output easier to read).