Button inherit stylesheet for no reason
-
The button "last_button" for some reason takes on the same style sheet as "the_button". This did not happen before I replaced QPushButton with QClickAgnostic.
MainWindow.h
private slots: void on_btn_left_click(); void on_btn_right_click(); private: QClickAgnostic * last_button = qobject_cast<QClickAgnostic *> ( sender() );
MainWindow.cpp
void MainWindow::on_btn_left_click() { // Styles the previously selected button to look like a normal button last_button->setStyleSheet(QString("QPushButton {color: #444444; background: #e6e6e6; border: 2px solid #cccccc; border-width: 0px 0px 2px 0px;} QPushButton:hover {border: 2px black solid; color: #333333;background-color: #F7F7F7;} QPushButton:pressed {background: #e6e6e6;}")); // retrieves the pressed button QClickAgnostic * the_button = qobject_cast<QClickAgnostic *> ( sender() ); if(the_button) { // code... // Styles the current button to look like a clicked button the_button->setStyleSheet(QString("QPushButton {color: #444444; background: #cccccc; border: 2px solid #cccccc; border-width: 0px 0px 2px 0px;} QPushButton:hover {border: 2px black solid; color: #333333; background-color: #F7F7F7;} QPushButton:pressed {background: #cccccc;}")); } // makes last button this button since this button will be last button next time a click event occurs // Has never, until QClickAgnostic, inherited the style sheet of the_button. last_button = the_button; }
qclickagnostic.h
#ifndef QCLICKAGNOSTIC_H #define QCLICKAGNOSTIC_H #include <QPushButton> #include <QMouseEvent> class QClickAgnostic : public QPushButton { Q_OBJECT public: explicit QClickAgnostic(QWidget *parent = nullptr); private slots: void mouseReleaseEvent(QMouseEvent *e); signals: void rightClicked(); void leftClicked(); public slots: }; #endif // QCLICKAGNOSTIC_H
qclickagnostic.cpp
#include "qclickagnostic.h" QClickAgnostic::QClickAgnostic(QWidget *parent) : QPushButton(parent) { // empty } void QClickAgnostic::mouseReleaseEvent(QMouseEvent *e) { if(e->button() == Qt::LeftButton) { emit leftClicked(); } else if(e->button() == Qt::RightButton) { emit rightClicked(); } }
-
Hi
But it seems you just set a pointer
last_button = the_button;
so last_button just points to the_button; and
hence it will look exactly the same. -
Yes it seems as if you're right. How do I solve this? I haven't had this issue before when I declared both the_button and last_button as QPushButton instead of my custom QPushButton class
-
@legitnameyo
I'm not an expert C++-er, but I don't get how your code works.private: QClickAgnostic * last_button = qobject_cast<QClickAgnostic *> ( sender() );
What is
sender()
at the point this is initialized?void MainWindow::on_btn_left_click() { last_button->setStyleSheet(QString("QPushButton {color: #444444; background: #e6e6e6; border: 2px solid #cccccc; border-width: 0px 0px 2px 0px;} QPushButton:hover {border: 2px black solid; color: #333333;background-color: #F7F7F7;} QPushButton:pressed {background: #e6e6e6;}"));
What is the value of
last_button
the very first time this function gets called? -
- . How do I solve this
By doing it the Qt way.
I assume you have a grid of buttons and only one to be selected at a given time so if you select another
it should be drawn as normal and new as pressed. At least that's how i read your code.You can do that very easily with a QButtonGroup and the Checkable property on each button.
Then Qt does the housekeeping for you.
You can style the look when "selected" with QPushButton:checked
That way you dont need last_button and you can apply the stylesheet to the parent and it will just work
with setting / resetting the style.result
-
What is sender() at the point this is initialized?
as it's a qobject_cast and doesn't crash on start up, most likely a nullptr?
What is the value of last_button the very first time this function gets called?
as it's not checked against 0, it should fail. Maybe luck?
using sender() is bad design anyway. One shouldn't use it if possible.
@mrjj posted a nice qt alternative I would suggest the OP to use that ;)
-
How do I implement this code way? I do my UI in code since that's what I prefer. This is what I've got so far and it isn't working...
QButtonGroup *g_btns = new QButtonGroup(this); /* all buttons are created and I add the buttons in about this way*/ btn1->setCheckable(true); //etc.. g_btns->addButton(btn1); g_btns->addButton(btn2); g_btns->addButton(btn3); // etc ... connect(g_btns, SIGNAL(buttonClicked(int)), this, SLOT(onGroupButtonClicked(int))); void MainWindow::onGroupButtonClicked(int btn_id) { qDebug() << "clicked!"; }
And this gives me nothing. The onGroupButtonClicked does not activate.
-
@legitnameyo I never used QButtonGroup, but a quick look into the documentation tells me, you never gave your added buttons an ID
void QButtonGroup::addButton(QAbstractButton *button, int id = -1)
I'm guessing here and say, that buttons with the ID of -1 do not emit the buttonClicked(int) signal
-
@legitnameyo It should work. Do you get any warnings at runtime (related to connect)?
Is g_btns in connect() really the one you're creating at the beginning of the code snippet you provided? -
@J.Hilk
Was a good guess,
but it seems, it will use negative values for auto numbering and does, in fact, emit them.QButtonGroup *buttonGroup = new QButtonGroup(this); buttonGroup->addButton( ui->pushButton_2); buttonGroup->addButton( ui->pushButton_3); buttonGroup->addButton( ui->pushButton_4); buttonGroup->addButton( ui->pushButton_5); connect(buttonGroup, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), [ = ](int id) { qDebug() << id; });
outputs.
-2
-2
-3
-5
-4 -
There is NO error such as this one below
QMetaObject::connectSlotsByName: No matching signal for onGroupButtonClicked(int)
And yes g_btns is defined only ONCE. Everything is in the order I got it in my code. However one thing that might change things up is that I use a custom class for my buttons called QClickAgnostic, which inherits from QPushButton as such above
and the buttons are created like this
QClickAgnostic *btn = new QClickAgnostic(ui->frame_of_btns);
-
@legitnameyo
You need to notify the ButtonGroup about the click event.I took a look at the source code of the abstractbutton and noticed the button directly notifies the group that it was clicked. But you broke this step when you reimplemented the MouseReleaseEvent function.
See a snippet of this step.
void QAbstractButton::mouseReleaseEvent(QMouseEvent *e) { ... if (hitButton(e->pos())) { d->repeatTimer.stop(); d->click(); // call click function e->accept(); } else { setDown(false); e->ignore(); } } void QAbstractButtonPrivate::click() { ... if (guard) emitReleased(); if (guard) emitClicked(); // call emitClicked } void QAbstractButtonPrivate::emitClicked() { ... #if QT_CONFIG(buttongroup) if (guard && group) { emit group->buttonClicked(group->id(q)); // emit the signal if (guard && group) emit group->buttonClicked(q); // emit the signal } #endif }
So, you can solve this problem calling the click() function inside MouseReleaseEvent.
void QClickAgnostic::mouseReleaseEvent(QMouseEvent *e) { if(e->button() == Qt::LeftButton) { click(); // called emit leftClicked(); } else if(e->button() == Qt::RightButton) { click(); // called emit rightClicked(); } }
-
@KillerSmath
Good digging ! -
@KillerSmath fix did the work, combined with @mrjj QGroupButton! I added this code to style the pressed button
void MainWindow::onGroupButtonClicked(int btn_id) { g_btns->button(btn_id)->setStyleSheet(QString("QPushButton {color: #444444; background: #cccccc; border: 2px solid #cccccc; border-width: 0px 0px 2px 0px;} QPushButton:hover {border: 2px black solid; color: #333333; background-color: #F7F7F7;} QPushButton:pressed {background: #cccccc;}")); }
Thanks a lot guys!