Qt QMenu setting a stylesheet - c++

I have a QMenu which I create like this.
QMenu *logoMenu = new QMenu();
I then add it to a QToolButton like so
logoButton->setMenu(logoMenu);
now I have an project.qss file which has the following stylesheet for the QMenu
QMenu#logoMenu {
background-color: #161614; /* sets background of the menu */
border: 0px solid #161614;
width: 150px;
position: absolute;
top: 50px;
}
QMenu::item#logoMenu {
background-color: transparent;
}
QMenu::item:selected#logoMenu {
background-color: #202020;
}
My problem is that the stylesheet does NOT get applies to the QMenu, I know I am loading the stylesheet correctly because I can style other widgets.
If I set the stylesheet manually like so
logoMenu->setStyleSheet("QMenu {.....}");
Here is how I create the QMenu:
logoMenu = new QMenu();
logoMenu->addAction(QString::fromUtf8("Import"));
logoMenu->addAction(QString::fromUtf8("Export"));
logoMenu->addAction(QString::fromUtf8("Help"));
logoMenu->addAction(QString::fromUtf8("Exit"));
logoMenu->setObjectName("logoMenu");
It works, no problem. Does anyone know why this happens?

Your Id selector is QMenu#logoMenu
It means Matches all "QMenu" instances whose object name is
"logoMenu". So you need to set object name of QMenu(
yourMenu->setObjectName( "logoMenu" ) )
Note:If QMenu is created using ui designer, Ui compiler will generate the code for yourMenu->setObjectName( "logoMenu" ). But if you are creating your own QMenu, you need to set object name explicitly to work your style type.

Judging from your comments under Ashifs answer you are missing a connection inside your Qt object tree. Try instantiating your QMenu with a parent that has a connection to the stylesheet. Probably just:
QMenu *logoMenu = new QMenu(this);
Alternatively you can set your stylesheet application global by adding it to the QApplication instance:
qApp->setStyleSheet("...");

Related

How apply different stylesheet to a QComboBox and its placeholder?

I want to distinguish the placeholder text of a QComboBox using QStyleSheet by drawing the placeholder with a different color.
With Qt6, it's easy to set the placeholder text to a combo box from code if the combo box is editable:
if(someCondition)
myComboBox->lineEdit()->setPlaceholder("Some placeholder");
else
myComboBox->lineEdit()->setPlaceholder("Some other placeholder");
So far so good, but if I use a custom stylesheet, so the default grayish placeholder is gone, and it is drawn with the color property. I tried to filter by some property based on this question, but I was not successful.
This is the relevant part of the dark-theme stylesheet:
auto styleSheet = "QWidget {color: white; background-color: #505050}"
"QComboBox[text=\"\"] { color: #808080 }";
myComboBox->setStyleSheet(styleSheet);
Currently, this is the result, with white letters:
And this is the expected with a sightly gray color:
Also, I tried to filter to the QComboBox, to the QComboBox[currentText=\"\"] but no success.
To draw the placeholder with darker pen, you have to modify the stylesheet and set to the lineEdit of the QComboBox.
auto styleSheet = "QWidget {color: white; background-color: #505050}"
"QLineEdit[text=\"\"] { color: #808080 }";
myComboBox->setStyleSheet(styleSheet);
myComboBox->lineEdit()->setStyleSheet(styleSheet);
QComboBox has no option to handle the placeholder text, because that text is handled by the line edit it has. Therefore, to alter the look and feel of the placeholder, you must use it's QLineEdit. Note, that several properties not make any effect on the line edit, like the background-color or border to say some, because those are handled by the QComboBox.
Also, if it's not automatically updated, you need to connect the change of the text with the stylesheet update. In the owning widget, connect the text change signal to the update:
connect(ui->myComboBox->lineEdit(), &QLineEdit::textChanged, this
[&]{ style()->polish(ui->myComboBox->lineEdit()); });

QT StyleSheet Theme for entire application using attribute selectors

Background:
I have a Qt application consisting of multiple dialogs and windows. I am trying to condense all styles into a single stylesheet which I want to load in my main.cpp with the aim of it being applied to my whole application (as I understand one should do). The application should not change styles from this point onwards.
I want to do this as styles can get mixed up, etc if one does this or something simliar for each widget in the QtCreator designer.
Problem:
I will explain a specific problem I face with an example from my application.
I have a couple of variations of simple dialogs, QLabel title, QLabel message (sometimes a QLabel hint), and either a single 'ok' QPushButton or 2 QPushButtons 'positive' & 'negative'.
For my theme, I would like to set styles for specific buttons, labels, etc which I got from here.
Example CSS:
QPushButton {
font-size: 10pt
color: #111
}
QPushButton[objectName="btnPostive"][objectName="btnProceed"] {
font-size: 1pt
color: #ccc
}
QLabel {
font-size: 9pt
color: #111
}
QLabel[objectName="lblTitle"] {
font-size: 9pt
color: #111
}
Please note, the [objectName="btnPostive"][objectName="btnProceed"] is intended to apply the style to buttons with the objectName's btnPostive and btnProceed however, it does not.
Is what I intend doing considered best practice, and a sub question (preferred example too) applying the same style to a select group of widgets, how should one best this.
If you want to control the applied stylesheet based on the object name, you can use the ID Selector QPushButton#objectName, see the full documentation. You separate multiple objects with the same stylesheet with a ,
Your stylesheet should then be this. Please note that you also need a ; at the end of each line.
QPushButton {
font-size: 10pt;
color: #111;
}
QPushButton#btnPositive, QPushButton#btnProceed {
font-size: 1pt;
color: #ccc;
}
QLabel {
font-size: 9pt;
color: #111;
}
QLabel#lblTitle {
font-size: 9pt;
color: #00f;
}

How can I set background for a QPushButton's tooltip?

In Qt I set a background image for a QPushButton, then I added a tooltip for this button and the tooltip has the same background image as the button and I couldn't change it with stylesheet, what am I missing?
In my code I have:
button->setStyleSheet("background-image: url(pathToImage);");
button->setToolTip("Click here");
In my style.qss I have:
QToolTip{
background-image: none;
background-color: white;
font-size: 20px;
border: 1px solid black;
}
The font-size and the border works, but the tooltip's background-image is the same as the button's.
I also tried adding another background-image to the tooltip, it didn't worked either.
How can I change the tooltip's background?
You have to specify the QWidget where to apply the property. If you dont do so, it will apply it to all the childrens of the widget.
In your case, to avoid the background image in the tooltip you have to specify that you want to apply that style to a QPushButton widget. The documentation says:
If we want the property to apply only to the QLineEdits that are children (or grandchildren or grand-grandchildren) of a specific dialog, we would rather do this:
myDialog->setStyleSheet("QLineEdit { background-color: yellow }");
In the example you mention, if you want to modify the style of the tooltip and the button, do something like this:
ui->pushButton->setStyleSheet(""
"QPushButton { background-image: url(me.png); }"
"QToolTip { color: #ffffff; background-color: #000000; border: 0px; }");
It will give you something like this
Update:
If you want to apply it to a single object and not the rest of the widgets of the same type, the documentation says:
If we want the property to apply only to one specific QLineEdit, we can give it a name using QObject::setObjectName() and use an ID Selector to refer to it:
myDialog->setStyleSheet("QLineEdit#nameEdit { background-color: yellow }");
So in your case:
ui->pushButton->setObjectName("awesomeButton");
ui->pushButton->setStyleSheet("QPushButton#awesomeButton { background-image: url(me.png); }");
When you set qss with setStyleSheet your stylesheet applies for all children of object. In your case you can avoid this using stylesheet for QPushButton only
button->setStyleSheet("QPushButton {background-image: url(pathToImage);}");

QMenu: Set text color for specific QAction

I have a QMenu as context menu that looks like this:
Menu
- information_A
- information_B
- information_C
Now i want the entry information_B to be painted in a different color. How can i archive this?
EDIT: I found the best solution in this post: link
In your case it would be as simple as:
QMenu contextMenu(this);
QString menuStyle(
"QMenu::item{"
"color: rgb(0, 0, 255);"
"}"
);
contextMenu.setStyleSheet(menuStyle);
For more options and possibilities take a look at the answer in the link I provided above.
PREVIOUS SOLUTION:
You can use QWidgetAction instead of QAction, and define your QLabel with text and stylesheet you want, and then assign it to your QWidgetAction. But keep in mind that you have to tweak the width and height of your QLabel, in order for it to look the same as QAction does.
Sample code:
// label
QLabel *text = new QLabel(QString("your text here"), this);
text->setStyleSheet("color: blue");
// init widget action
QWidgetAction *widAct= new QWidgetAction(this);
widAct->setDefaultWidget(text);
contextMenu.addAction(widAct);
If you are only looking to style a single item in the menu, you can set it as default with QMenu::setDefaultAction and style a default menu item with the QMenu::item:default selector.
I.e.:
QMenu* menu = new QMenu("My menu");
QAction* actionToStyle = new QAction("My action");
menu->addAction(actionToStyle);
menu->setDefaultAction(actionToStyle);
menu->setStyleSheet("QMenu::item:default { color: #ff0000; }");
The limitation of this method is that it can apply special styling to only one item.

How to get opacity to main window & widgets on button click in Windows using Qt 4.8?

I'm bit new to Qt framework, so am struggling bit in one of the requirement.
We have to fade the main window on button click which in turns pop-up the confirmation message. With that only the pop-up message should be visible and the background should get opaque.
Currently on clicking the button the message is displayed the background gets opaque. But the other widgets in the windows are still prominent.
Below is the code snippet on Click event of Ok Button
void MainWindow::OkClicked()
{
QGraphicsOpacityEffect* effect01 = new QGraphicsOpacityEffect();
effect01->setOpacity(0.2);
this->setGraphicsEffect(effect01);
MessageDialog->updateStyles(); //Pop-up message Box
MessageDialog->show();
}
One approach can be, if we set the opacity for all widgets individually. But that won't be a good design
Any guidance is highly appreciated.
It's possible to create a containing widget and add a QSS styling with a background-color property with an alpha property. Then add layouts to your containing widget for organizing the layout of the nested widgets. I use this technique to achieve a transparency effect while maintaining opacity for the nested controls. Here's some example code:
setAttribute(Qt::WA_NoSystemBackground, true);
// set the parent widget's background to translucent
setAttribute(Qt::WA_TranslucentBackground, true);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
// create a display widget for displaying child widgets
QWidget* displayWidget = new QWidget;
displayWidget->setGeometry(0, 0, this->width(), this->height());
displayWidget->setStyleSheet(".QWidget { background-color: rgba(0, 0, 0, 75%); border-width: 1px; border-style: solid; border-radius: 5px; border-color: #555555; } .QWidget:hover { background-color: rgba(68, 68, 68, 75%); border-width: 2px; border-style: solid; border-radius: 10px; border-color: #ffffff; }");
QLabel* icon = new QLabel;
icon->setPixmap(pixmapIcon);
icon->setMaximumSize(32, 32);
QLabel* header = new QLabel;
header->setMaximumSize(225, 50);
header->setWordWrap(true);
header->setText(headerText);
header->setStyleSheet("QLabel { color: #ffffff; font-weight: bold; font-size: 12px; }");
QLabel* message = new QLabel;
message->setMaximumSize(225, 100);
message->setWordWrap(true);
message->setText(messageText);
message->setStyleSheet("QLabel { color: #ffffff; font-size: 10px; }");
QHBoxLayout* displayMainLayout = new QHBoxLayout;
displayMainLayout->addWidget(icon);
QVBoxLayout* vl = new QVBoxLayout;
vl->addWidget(header);
vl->addWidget(message);
displayMainLayout->addLayout(vl);
displayWidget->setLayout(displayMainLayout);
QHBoxLayout* containerLayout = new QHBoxLayout;
containerLayout->addWidget(displayWidget);
setLayout(containerLayout);
show();
This code is taken directly from my Qt Tray Notification Manager project. You can view the full code here to get some context: https://github.com/pcmantinker/Tray-Notification-System
Note, if you're familiar with CSS, QSS is very similar. If you want to style all QWidgets a certain way, you would use the QWidget selector. However, if you just want to style a particular QWidget, use the .QWidget selector. Styling all QWidgets would make every visible QWidgets inherit the same properties as each UI element is derived from QWidget. Keep that in mind when building the styles. Here's a reference to QSS: http://qt-project.org/doc/qt-4.8/stylesheet.html
Here's some sample images of how it looks:
Windows 7
Mac OS X Lion
Ubuntu
I hope this helps. Let me know if you have any questions.