How to apply CSS styles only to certain items in menu and tool bar?
-
I have a menu and a tool bar with a bunch of action items.
menu->setStyleSheet("QMenu { text-decoration: line-through; }"); toolbar->setStyleSheet("QToolButton { text-decoration: line-through; }");
It works fine for all items, but I need it for specific items.
So how to apply CSS styles only to certain items in the menu and tool bar?
-
You can do this with a dynamic property: https://wiki.qt.io/Dynamic_Properties_and_Stylesheets
-
"Customizing Using Dynamic Properties" is the way to go , but how to do it right?
#include "mainwindow.h" #include <QDebug> #include <QStyle> #include <QToolBar> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setStyleSheet("*[invertItem=true] { text-decoration: line-through }"); QAction *actionQuit = new QAction("Quit", this); connect(actionQuit, &QAction::triggered, this, &MainWindow::close); m_actionItem = new QAction("Item", this); m_actionItem->setProperty("invertItem", false); QAction *actionInvert = new QAction("Invert", this); actionInvert->setCheckable(true); connect(actionInvert, &QAction::toggled, [=](bool checked) { this->on_actionInvert_toggled(checked); }); m_toolBar = addToolBar("Toolbar"); m_toolBar->addAction(actionQuit); m_toolBar->addSeparator(); m_toolBar->addAction(m_actionItem); m_toolBar->addSeparator(); m_toolBar->addAction(actionInvert); } void MainWindow::on_actionInvert_toggled(bool checked) { qInfo() << checked; m_actionItem->setProperty("invertItem", checked); }
what am i missing?
-
@NotNypical
At a glance, have you remembered that after changing the value of a dynamic property you have topolish()
any widgets using it? If not it does not update, if that's what you're seeing?That was in the link @Christian-Ehrlicher gave you:
Limitations
There are limitations to using this trick. The main one is that the style will not update itself automatically when the value of a property referenced from the style sheet changes. Instead, you must manually trigger an update of the visual appearance of a widget when a styled property changes. For example:
myLineEdit->setProperty("urgent", true); myLineEdit->style()->unpolish(myLineEdit); myLineEdit->style()->polish(myLineEdit);
Note that this must be done in the widget to which the style was applied. QStyle::polish accepts either a QWidget or a QApplication as a parameter.
In my (old, Python) code I defined:
def widgetPropertyChanged(widget: QWidget): # Whenever a widget property is changed # (widget.setProperty() or something like QLineEdit.setReadOnly()) called to alter a property after initialisation) # we have to "alter" widget's stylesheet to cause Qt to refresh for the property change # ss = widget.styleSheet() # widget.setStyleSheet("/* */" + (ss if ss is not None else "")) # widget.setStyleSheet(ss) widget.style().unpolish(widget) widget.style().polish(widget)
-
@NotNypical
When you wrote earlierwhat am i missing?
without any comment at all as to what was/was not happening which you did/did not expect. So I have no idea what your issue is, if any. I don't even know what behaviour you are or are not seeing.
If the object you are setting a property on is not a widget, what is a stylesheet testing the property going to do?
If it's to work at all, maybe you need to polish the app/main window/menu/toolbar, I don't know.
Maybe I'm mistaken, so I'll back out now....
P.S.
I think the first thing I would try is:m_actionItem = new QAction("Item", this); m_actionItem->setProperty("invertItem", true); ... m_toolBar->addAction(m_actionItem);
Note I have set it to
true
before adding it. This eliminates changing the dynamic property. I'm thinking/hoping this should work because it's before adding the action to the menu/showing it. This needs to work right before you worry about altering it dynamically, I don't know whether it does or not. -
This works:
void MainWindow::on_actionInvert_toggled(bool checked) { auto widgetItem = m_toolBar->widgetForAction(m_actionItem); widgetItem->setProperty("invertItem", checked); widgetItem->style()->unpolish(widgetItem); widgetItem->style()->polish(widgetItem); }
https://doc.qt.io/qt-5/qtoolbar.html#widgetForAction
It returns the widget associated with the specified action.Now I am looking for a solution for menu items.
-
Hi,
Why not set everything up first and the. Apply the style sheet at the end ?