Changing Q_PROPERTY in pseudo state of a widget stylesheet does not notify
-
Hi,
I customized QLineEdit by deriving from it. Then added an action and set an icon. The icon is set via a propery in the stylesheet.
For the read-only pseudo state of the line edit, another icon must be selected. The stylesheet defines this by having a different value for the icon property at the read-only state.The icon property has a notify function that signals the IconChanged function.
ClearIconChanged is called once at initialization but not when the widget is set to read-only later.For testing I defined in the stylesheet a green background color for the read-only state. This works, the background color changes when toggling read-only.
Class:
class QMyLineEdit : public QLineEdit { Q_OBJECT Q_PROPERTY( QString action_icon MEMBER m_strIcon NOTIFY IconChanged ) public: explicit QMyLineEdit( QWidget* parent ) : QLineEdit( parent ) , m_pAction( nullptr ) { m_pAction = new QAction( this ); connect( m_pClearAction, &QAction::triggered, this, &QMyLineEdit::MyAction ); addAction( m_pAction, QLineEdit::TrailingPosition ); connect( this, &QMyLineEdit::IconChanged, this, &QMyLineEdit::UpdateIcon ); } private: QAction* m_pAction; QString m_strIcon; signals: void IconChanged(); private slots: void UpdateIcon() { QIcon ClearIcon( m_strClearIcon ); m_pAction->setIcon( ClearIcon ); } void MyAction() { /* ... */ } };
Stylesheet
.QMyLineEdit { qproperty-action_icon: url(:/Widgets/action.png); } .QMyLineEdit:read-only { background-color: green; qproperty-action_icon: url(:/Widgets/action_readonly.png); }
Now my questions.
Are changing properties in a pseudo state supported?
What is the common way to get such behavior? -
I believed NOTIFY means that Qt emits the signal when the property was changed.
Now I changed the property definition to
Q_PROPERTY( QString action_icon READ GetActionIcon WRITE SetActionIcon )
so I can debug when its read and written.
The breakpoints were hit on initialization, the property was read once before it was set and later it was set with the default (non-pseudo state value). They were not hit when the state changed.
-
@kshegunov
I think my last version of Q_PROPERTY definition is right. If somehow the property changes, it must call the SetActionIcon function.But why is SetActionIcon function not called when toggling the read-only pseudo state of QMyLineEdit?
-
@Arie
Maybe there's some confusion. You either do this:Q_PROPERTY( QString action_icon MEMBER m_icon READ GetActionIcon WRITE SetActionIcon NOTIFY actionChanged)
and when
SetActionIcon
is called theactionChanged
will be emitted.Or you do it like this:
class QMyLineEdit : public QLineEdit { Q_PROPERTY( QString action_icon READ GetActionIcon WRITE SetActionIcon NOTIFY actionChanged) // ... }; QString QMyLineEdit::GetActionIcon() { return m_icon; } void QMyLineEdit::SetActionIcon(const QString & icon) { m_icon = icon; emit actionChanged(); }
In any case emitting
actionChanged()
will not triggerSetActionIcon
, because it's to notify others that the property has changed, not the other way around.Kind regards.
-
@kshegunov
I think too there is some confusion.
This is the updated version of the class. QPROPERTY now only takes READ and WRITE functions, NOTIFY is left out.class QMyLineEdit : public QLineEdit { Q_OBJECT Q_PROPERTY( QString action_icon READ GetIcon WRITE SetIcon ) public: explicit QMyLineEdit( QWidget* parent ) : m_pAction( nullptr ) { m_pAction = new QAction( this ); connect( m_pAction, &QAction::triggered, this, &QMyLineEdit::MyAction ); addAction( m_pAction, QLineEdit::TrailingPosition ); } private: QAction* m_pAction; QString m_strIcon; const QString& GetIcon() const { /* Breakpoint hit at initialization, before SetIcon */ return m_strClearIcon; } void SetIcon( const QString& strIcon ) { /* Breakpoint hit at initialization but not when read-only was * toggled via QLineEdit::setReadOnly() */ m_strIcon = strIcon; QIcon Icon( m_strIcon ); m_pAction->setIcon( Icon ); } void MyAction(){ /* ... */ } };
The stylesheet part remained same.
.QMyLineEdit { qproperty-action_icon: url(:/Widgets/action.png); } .QMyLineEdit:read-only { background-color: green; qproperty-action_icon: url(:/Widgets/action_readonly.png); }
In short my issue: Toggling read-only with setReadOnly( bool ) toggles the background color but not my action's icon.