How to change the QToolButton opacity when the cursor is on int?
-
I have created a button and set a text and icon to it. By using CSS, I have decreased the button background color and the text opacity and increased them when the cursor is on the button (hover in CSS). As far as I know, It's not possible to set opacity for the icon using CSS, so that I have used QPainter to set the opacity to my icon. I have two problems:
1: the opacity is not set to my icon (when I run the program, I get my default icon ).
2: how can I change the opacity of my icon when the cursor is on it?
I would appreciate if someone could help me.Here is my code:
QToolButton *butt= new QToolButton(this); butt->setFixedSize(widthW/2.5,heightW/2.5); int width_button_EM = butt->frameGeometry().width(); int height_buttin_EM = butt->frameGeometry().height(); butt->setGeometry(widthW*50/100,heightW*20/100,width_button_EM,height_buttin_EM); butt->setObjectName("butt-name"); butt->setStyleSheet( "QToolButton#butt-name {" "background-color: rgba( 90, 233, 240, 20%);" "color:rgba(38, 12, 12, 20%); " "}" "QToolButton#butt-name {" "border:5px solid #303030;" "border-width: 3px;" " }" " QToolButton#butt-name {" " border-radius: 0px;" " }" " QToolButton#butt-name:hover {" "background-color: rgba( 90, 233, 240, 100%);" "color:rgba(38, 12, 12, 100%); " " }" "QToolButton#butt-name {" "padding-left:5px; padding-right:5px; padding-bottom:5px; padding-top:5px;" "}" ); QImage image; image.load("F:/qt codes/eqatuapp/animation/EqProjectFS/2-2"); image = image.convertToFormat(QImage::Format_ARGB32); QPainter painter(&image); painter.setOpacity(0.5); QPixmap pixmap = QPixmap::fromImage(image); QIcon icon(pixmap); butt->setIcon(icon); butt->setIconSize(QSize(widthW/2,heightW/3.3)); butt->setText("my book"); butt->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); butt->setCursor(Qt::PointingHandCursor);
Here is the output:
UPDATE:
I found out how to change the opacity of the whole button (the background, the icon and also the text), by using QGraphicsOpacityEffect. Now my problem is how to change the opacity of the button when a cursor is on it. Is there a specific signal for it?
Here is my updated code:QImage image; image.load("F:/qt codes/eqatuapp/animation/EqProjectFS/2-2"); image = image.convertToFormat(QImage::Format_ARGB32); QPainter painter(&image); painter.setOpacity(0.5); QPixmap pixmap = QPixmap::fromImage(image); QIcon icon(pixmap); butt->setIcon(icon); butt->setIconSize(QSize(widthW/2,heightW/3.3)); butt->setText("my book"); butt->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); butt->setCursor(Qt::PointingHandCursor); QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(this); effect->setOpacity(0.5); butt->setGraphicsEffect(effect);
the output:
-
@nanor said in How to change the QToolButton opacity when the cursor is on int?:
Now my problem is how to change the opacity of the button when a cursor is on it. Is there a specific signal for it?
No signals, but events.
-
@Pl45m4 Thank you for reply. I set setAttribute(Qt::WA_Hover, true) to my button and then Implemented Dialog::enterEvent(QEvent * event), but I can't get the result I want.
Here is my updated code:dialog.h:
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QToolButton> #include <QGraphicsOpacityEffect> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); QToolButton *butt; QGraphicsOpacityEffect *effect; private: Ui::Dialog *ui; protected: void enterEvent(QEvent * event); }; #endif // DIALOG_H
dialog.cpp:
butt= new QToolButton(this); butt->setFixedSize(widthW/2.5,heightW/2.5); int width_button_EM = butt->frameGeometry().width(); int height_buttin_EM = butt->frameGeometry().height(); butt->setGeometry(widthW*50/100,heightW*20/100,width_button_EM,height_buttin_EM); butt->setObjectName("butt-name"); butt->setStyleSheet( "QToolButton#butt-name {" "border:5px solid #303030;" "border-width: 3px;" " }" " QToolButton#butt-name {" " border-radius: 0px;" " }" "QToolButton#butt-name {" "padding-left:5px; padding-right:5px; padding-bottom:5px; padding-top:5px;" "}" ); QImage image; image.load("F:/qt codes/opacity4/2-2"); image = image.convertToFormat(QImage::Format_ARGB32); QPainter painter(&image); painter.setOpacity(0.5); QPixmap pixmap = QPixmap::fromImage(image); QIcon icon(pixmap); butt->setIcon(icon); butt->setIconSize(QSize(widthW/2,heightW/3.3)); butt->setText("my book"); butt->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); butt->setCursor(Qt::PointingHandCursor); effect = new QGraphicsOpacityEffect(this); effect->setOpacity(0.5); butt->setGraphicsEffect(effect); butt->setAttribute(Qt::WA_Hover, true); } Dialog::~Dialog() { delete ui; } void Dialog::enterEvent(QEvent * event) { QDialog::enterEvent(event); effect->setOpacity(1); butt->setGraphicsEffect(effect); }
I would appreciate if you could help me in this matter.
-
Not
QDialog
's enter event,QToolButton
's.
Then you can install an eventFilter to handle the mouse enter / leave events and apply the opacity effect (that's how I would do it and have done with a custom widget before).
In addition, I think, you also need to enable mouse tracking on your widget (yourQToolButton
), in order to track the mouse movement, even when there is no real action like mouse clicks happening.Add this to your
Dialog.h
protected: bool eventFilter(QObject *obj, QEvent *event) override;
then re-implement it just about like this:
bool Dialog::eventFilter(QObject *obj, QEvent *event) { if(obj == YOUR_BUTTON) { if(event->type() == QEvent::Enter) { // SET YOUR OPACITY } else if(event->type() == QEvent::Leave) { // SET OPACITY BACK TO NORMAL } return true; } else { return QDialog::eventFilter(obj, event); } }
Don't forget:
(put this in yourcpp
file, in yourdialog
constructor)// enable mouse tracking YOUR_BUTTON->setMouseTracking(true); // Install event filter on your button YOUR_BUTTON->installEventFilter(this); // this = your dialog
You can also add animation effects to make it look smooth. Otherwise you get some 2-state behavior, instant opaque when the mouse left the button and your pre-set value, as soon as it enters again.
QPropertyAnimation *animation = new QPropertyAnimation(effect, "opacity"); animation->setDuration(1000); // duration time in msecs animation->setStartValue(1); // 1 to fadeOut, start with 0.5 (or some X<1) to fadeIn animation->setEndValue(0.5); // change end value with start value animation->setEasingCurve(QEasingCurve::InQuart); // OutQuart for fadeOut animation->start(QPropertyAnimation::DeleteWhenStopped);
This can be called here, for example:
if(event->type() == QEvent::Enter)
{
// SET YOUR OPACITY
}
else if(event->type() == QEvent::Leave)
{
// SET OPACITY BACK TO NORMAL
} -
@Pl45m4 Thank you so much for your complete reply. I set your code into my project, but I got some errors . Here is my updated code:
dialog.h:
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QToolButton> #include <QGraphicsOpacityEffect> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); QToolButton *butt; QGraphicsOpacityEffect *effect; private: Ui::Dialog *ui; protected: void enterEvent(QEvent * event); bool eventFilter(QObject *obj, QEvent *event) override; }; bool Dialog::eventFilter(QObject *obj, QEvent *event) { if(obj == butt) { if(event->type() == QEvent::Enter) { // SET YOUR OPACITY effect->setOpacity(1); butt->setGraphicsEffect(effect); } else if(event->type() == QEvent::Leave) { // SET OPACITY BACK TO NORMAL effect->setOpacity(0.5); butt->setGraphicsEffect(effect); } return true; } else { return QDialog::eventFilter(obj, event); } } #endif // DIALOG_H
dialog.cpp:
QImage image; image.load("F:/qt codes/opacity4/2-2"); image = image.convertToFormat(QImage::Format_ARGB32); QPainter painter(&image); painter.setOpacity(0.5); QPixmap pixmap = QPixmap::fromImage(image); QIcon icon(pixmap); butt->setIcon(icon); butt->setIconSize(QSize(widthW/2,heightW/3.3)); butt->setText("my book"); butt->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); butt->setCursor(Qt::PointingHandCursor); effect = new QGraphicsOpacityEffect(this); effect->setOpacity(0.5); butt->setGraphicsEffect(effect); //butt->setAttribute(Qt::WA_Hover, true); butt->setMouseTracking(true); butt->installEventFilter(this); } Dialog::~Dialog() { delete ui; } void Dialog::enterEvent(QEvent * event) { QToolButton::enterEvent(event); effect->setOpacity(1); butt->setGraphicsEffect(effect); }
Have I written the part re-implementation (bool Dialog::eventFilter(QObject *obj, QEvent *event)) in the correct place?
The errors I get:
-
@nanor said in How to change the QToolButton opacity when the cursor is on int?:
Have I written the part re-implementation (bool Dialog::eventFilter(QObject *obj, QEvent *event)) in the correct place?
This belongs in your
dialog.cpp
. If this does not help, also#include <QEvent>
.... and remove or comment your
Dialog::EnterEvent
. It will always fire, when you move your mouse over your dialog.BTW:
butt
is a hilarious name for a button :D -
@Pl45m4 I added #include<QEvent> to both dialog.h and dialog.cpp files and commented the part:
void Dialog::enterEvent(QEvent * event) { QToolButton::enterEvent(event); effect->setOpacity(1); butt->setGraphicsEffect(effect); }
but I got error.
Here is my updated code:
dialog.h:
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QToolButton> #include <QGraphicsOpacityEffect> #include <QEvent> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); QToolButton *butt; QGraphicsOpacityEffect *effect; private: Ui::Dialog *ui; protected: void enterEvent(QEvent * event); bool eventFilter(QObject *obj, QEvent *event) override; }; bool Dialog::eventFilter(QObject *obj, QEvent *event) { if(obj == butt) { if(event->type() == QEvent::Enter) { // SET YOUR OPACITY effect->setOpacity(1); butt->setGraphicsEffect(effect); } else if(event->type() == QEvent::Leave) { // SET OPACITY BACK TO NORMAL effect->setOpacity(0.5); butt->setGraphicsEffect(effect); } return true; } else { return QDialog::eventFilter(obj, event); } } #endif // DIALOG_H
dialog.cpp:
QImage image; image.load("F:/qt codes/opacity4/2-2"); image = image.convertToFormat(QImage::Format_ARGB32); QPainter painter(&image); painter.setOpacity(0.5); QPixmap pixmap = QPixmap::fromImage(image); QIcon icon(pixmap); butt->setIcon(icon); butt->setIconSize(QSize(widthW/2,heightW/3.3)); butt->setText("my book"); butt->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); butt->setCursor(Qt::PointingHandCursor); effect = new QGraphicsOpacityEffect(this); effect->setOpacity(0.5); butt->setGraphicsEffect(effect); //butt->setAttribute(Qt::WA_Hover, true); butt->setMouseTracking(true); butt->installEventFilter(this); } Dialog::~Dialog() { delete ui; } /*void Dialog::enterEvent(QEvent * event) { QToolButton::enterEvent(event); effect->setOpacity(1); butt->setGraphicsEffect(effect); }*/
The error I got:
-
Not in both. Only in your header is enough. Your
cpp
already includes your header file.And you didn't move the implemention from your header to your code file.
Only this
bool eventFilter(QObject *obj, QEvent *event) override;
should stay in your header.
What to put where, is general OOP / C++ knowledge ;-)
-
@nanor said in How to change the QToolButton opacity when the cursor is on int?:
remove the line void enterEvent(QEvent * event);
Or comment it to test if my code works for you. You dont need a
QDialog::EnterEvent
. AND move theeventFilter
implementation to yourcpp
. The errors should be gone now. -
-
AHHHHHH.
No :)
This (
bool eventFilter(QObject *obj, QEvent *event) override;
) is not the implementation.HEADER (
Dialog.h
)protected: bool eventFilter(QObject *obj, QEvent *event) override;
DIALOG.CPP
bool Dialog::eventFilter(QObject *obj, QEvent *event) { if(obj == YOUR_BUTTON) { if(event->type() == QEvent::Enter) { // SET YOUR OPACITY } else if(event->type() == QEvent::Leave) { // SET OPACITY BACK TO NORMAL } return true; } else { return QDialog::eventFilter(obj, event); }
-
@Pl45m4 Really sorry :( I set that part to my cpp file :
QImage image; image.load("F:/qt codes/opacity4/2-2"); image = image.convertToFormat(QImage::Format_ARGB32); QPainter painter(&image); painter.setOpacity(0.5); QPixmap pixmap = QPixmap::fromImage(image); QIcon icon(pixmap); butt->setIcon(icon); butt->setIconSize(QSize(widthW/2,heightW/3.3)); butt->setText("my book"); butt->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); butt->setCursor(Qt::PointingHandCursor); effect = new QGraphicsOpacityEffect(this); effect->setOpacity(0.5); butt->setGraphicsEffect(effect); //butt->setAttribute(Qt::WA_Hover, true); butt->setMouseTracking(true); butt->installEventFilter(this); } Dialog::~Dialog() { delete ui; } bool Dialog::eventFilter(QObject *obj, QEvent *event) { if(obj == butt) { if(event->type() == QEvent::Enter) { // SET YOUR OPACITY effect->setOpacity(1); butt->setGraphicsEffect(effect); } else if(event->type() == QEvent::Leave) { // SET OPACITY BACK TO NORMAL effect->setOpacity(0.5); butt->setGraphicsEffect(effect); } return true; } else { return QDialog::eventFilter(obj, event); } } /*void Dialog::enterEvent(QEvent * event) { QToolButton::enterEvent(event); effect->setOpacity(1); butt->setGraphicsEffect(effect); }*/
But got this error:
-
@Pl45m4 Oh sorry. I have thought you mean the protected part of the header file.
My header file now is:#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QToolButton> #include <QGraphicsOpacityEffect> #include <QEvent> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); QToolButton *butt; QGraphicsOpacityEffect *effect; private: Ui::Dialog *ui; protected: bool eventFilter(QObject *obj, QEvent *event) override; }; #endif // DIALOG_H
and my cpp file is:
#include "dialog.h" #include "ui_dialog.h" #include <QDesktopWidget> #include <QIcon> #include <QPixmap> #include <QToolButton> #include <QImage> #include <QPainter> #include <QGraphicsOpacityEffect> #include <QDebug> Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); QDesktopWidget wid; int screenWidth = wid.screen()->width(); int screenHeight = wid.screen()->height(); this->setFixedSize(screenWidth/2.5,screenHeight/1.5); int widthW = this->frameGeometry().width(); int heightW = this->frameGeometry().height(); //qDebug() << widthW; //qDebug() << heightW; this->setGeometry((screenWidth/2)-(widthW/2),(screenHeight/2)-(heightW/2),widthW,heightW); butt= new QToolButton(this); butt->setFixedSize(widthW/2.5,heightW/2.5); int width_button_EM = butt->frameGeometry().width(); int height_buttin_EM = butt->frameGeometry().height(); butt->setGeometry(widthW*50/100,heightW*20/100,width_button_EM,height_buttin_EM); butt->setObjectName("butt-name"); butt->setStyleSheet( "QToolButton#butt-name {" "border:5px solid #303030;" "border-width: 3px;" " }" " QToolButton#butt-name {" " border-radius: 0px;" " }" "QToolButton#butt-name {" "padding-left:5px; padding-right:5px; padding-bottom:5px; padding-top:5px;" "}" ); QImage image; image.load("F:/qt codes/opacity4/2-2"); image = image.convertToFormat(QImage::Format_ARGB32); QPainter painter(&image); painter.setOpacity(0.5); QPixmap pixmap = QPixmap::fromImage(image); QIcon icon(pixmap); butt->setIcon(icon); butt->setIconSize(QSize(widthW/2,heightW/3.3)); butt->setText("my book"); butt->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); butt->setCursor(Qt::PointingHandCursor); effect = new QGraphicsOpacityEffect(this); // effect->setOpacity(0.5); //butt->setGraphicsEffect(effect); //butt->setAttribute(Qt::WA_Hover, true); butt->setMouseTracking(true); butt->installEventFilter(this); } Dialog::~Dialog() { delete ui; } bool Dialog::eventFilter(QObject *obj, QEvent *event) { if(obj == butt) { if(event->type() == QEvent::Enter) { // SET YOUR OPACITY effect->setOpacity(1); butt->setGraphicsEffect(effect); } else if(event->type() == QEvent::Leave) { // SET OPACITY BACK TO NORMAL effect->setOpacity(0.5); butt->setGraphicsEffect(effect); } return true; } else { return QDialog::eventFilter(obj, event); } }
But the output is only an empty dialog window without button and button icon.
-
How is your button set to your dialog and where?
QDesktopWidget
is deprecated and shouldn't be used anymore. All in all, you picked the wrong approach. Better apply someQLayout
(horizontal or vertical) to yourQDialog
and then add your button. -
@Pl45m4 Actually I have used QDesktopWidget, because I want to set the geometry based on my screen width and height.
When I comment the part:
bool Dialog::eventFilter(QObject *obj, QEvent *event) { if(obj == butt) { if(event->type() == QEvent::Enter) { effect->setOpacity(1); butt->setGraphicsEffect(effect); } else if(event->type() == QEvent::Leave) { effect->setOpacity(0.5); butt->setGraphicsEffect(effect); } return true; } else { return QDialog::eventFilter(obj, event); } }
from my cpp file , and the part:
protected: bool eventFilter(QObject *obj, QEvent *event) override;
from my header file, I got the following output:
And when I don't comment those parts, I got an empty dialog window.
-
@nanor said in How to change the QToolButton opacity when the cursor is on int?:
I want to set the geometry based on my screen width and height
QScreen
is the alternative / replacement.
https://doc.qt.io/qt-5/qscreen.htmlYour button is floating around / just drawn on your widget (dialog).
It is always better to use layouts unless there is any reason to not, which I dont see in your case :)
dialog.cpp
(afterbutt->setCursor(Qt::PointingHandCursor);
)QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(butt); setLayout(layout);
-
@Pl45m4 I added the layout and now my cpp file is:
#include "dialog.h" #include "ui_dialog.h" #include <QDesktopWidget> #include <QIcon> #include <QPixmap> #include <QToolButton> #include <QImage> #include <QPainter> #include <QGraphicsOpacityEffect> #include <QDebug> #include <QVBoxLayout> Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); /*QDesktopWidget wid; int screenWidth = wid.screen()->width(); int screenHeight = wid.screen()->height(); this->setFixedSize(screenWidth/2.5,screenHeight/1.5); int widthW = this->frameGeometry().width(); int heightW = this->frameGeometry().height(); qDebug() << widthW; qDebug() << heightW; this->setGeometry((screenWidth/2)-(widthW/2),(screenHeight/2)-(heightW/2),widthW,heightW); butt->setFixedSize(widthW/2.5,heightW/2.5); int width_button_EM = butt->frameGeometry().width(); int height_buttin_EM = butt->frameGeometry().height(); butt->setGeometry(widthW*50/100,heightW*20/100,width_button_EM,height_buttin_EM);*/ butt= new QToolButton(this); butt->setObjectName("butt-name"); butt->setStyleSheet( "QToolButton#butt-name {" "border:5px solid #303030;" "border-width: 3px;" " }" " QToolButton#butt-name {" " border-radius: 0px;" " }" "QToolButton#butt-name {" "padding-left:5px; padding-right:5px; padding-bottom:5px; padding-top:5px;" "}" ); QImage image; image.load("F:/qt codes/opacity4/2-2"); image = image.convertToFormat(QImage::Format_ARGB32); QPainter painter(&image); painter.setOpacity(0.5); QPixmap pixmap = QPixmap::fromImage(image); QIcon icon(pixmap); butt->setIcon(icon); // butt->setIconSize(QSize(widthW/2,heightW/3.3)); butt->setIconSize(QSize(100,200)); butt->setText("my book"); butt->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); butt->setCursor(Qt::PointingHandCursor); effect = new QGraphicsOpacityEffect(this); effect->setOpacity(0.5); butt->setGraphicsEffect(effect); //butt->setAttribute(Qt::WA_Hover, true); butt->setMouseTracking(true); butt->installEventFilter(this); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(butt); setLayout(layout); } Dialog::~Dialog() { delete ui; } bool Dialog::eventFilter(QObject *obj, QEvent *event) { if(obj == butt) { if(event->type() == QEvent::Enter) { effect->setOpacity(1); butt->setGraphicsEffect(effect); } else if(event->type() == QEvent::Leave) { effect->setOpacity(0.5); butt->setGraphicsEffect(effect); } return true; } else { return QDialog::eventFilter(obj, event); } }
Again, when I don't comment the eventfilter parts, the output is an empty dialog window and when I comment those parts, I got:
The reason I use QDesktopWidget is that I want to have my program exe file and then use the program in different computers with different widths and heights, so I have to set geometry to my elements based on the screen geometry.
-
@Pl45m4 Hi. Finally I succeed! I changed the protected part of my header file to:
protected: bool eventFilter(QObject *obj, QEvent *event){ if(obj == butt) { if(event->type() == QEvent::Enter) { effect->setOpacity(1); butt->setGraphicsEffect(effect); } else if(event->type() == QEvent::Leave) { effect->setOpacity(0.5); butt->setGraphicsEffect(effect); } } }
and clear the bool part from the cpp file and my code worked fine.
Thank you so much for the code you provided yesterday. Really appreciate your help .
Best regards.