简体   繁体   中英

QPushButton doesn't update when setDown is called

I have a QPushButton , I want to make it "pushed in" so I call

btn->setDown(true);

But this doesn't update the appearance or the behavior of the button (it's still raised, and pressable).

This happens when I call the command from a general function, but when I call it from a function that is triggered when it's pressed (by binding a slot to its clicked() signal ).

The value of the property down is true, as expected, but the behaviour doesn't match. What is missing?

I did what you described in an MCVE . (Strictly speaking: I did it how I understood what you described...)

This is my sample testQPushButtonSetDown.cc :

// Qt header:
#include <QtWidgets>

#if QT_VERSION_MAJOR < 5
#define USE_OLD_SIGNAL_SLOT
#endif // QT_VERSION_MAJOR < 5

#ifdef USE_OLD_SIGNAL_SLOT
#include "PushButton.h"
#else // (not) USE_OLD_SIGNAL_SLOT
#define PushButton QPushButton
#endif // USE_OLD_SIGNAL_SLOT

int main(int argc, char **argv)
{
  qDebug() << QT_VERSION_STR;
  // main application
#undef qApp // undef macro qApp out of the way
  QApplication qApp(argc, argv);
  qDebug() << QApplication::style()->objectName();
  // setup GUI
  QWidget qWin;
  QHBoxLayout qBox;
  QCheckBox qTglBtn(QString::fromUtf8("Force Button Down"));
  qBox.addWidget(&qTglBtn);
  PushButton qBtn(QString::fromUtf8("A Button"));
  qBtn.setFocusPolicy(Qt::StrongFocus); // requirement of OP
  qBox.addWidget(&qBtn);
  qWin.setLayout(&qBox);
  qWin.show();
  // install signal handlers
#ifdef USE_OLD_SIGNAL_SLOT
  QObject::connect(&qTglBtn, SIGNAL(toggled(bool)),
    &qBtn, SLOT(setDown(bool)));
#else  // (not) USE_OLD_SIGNAL_SLOT
  QObject::connect(&qTglBtn, &QCheckBox::toggled,
    &qBtn, &PushButton::setDown);
#endif // USE_OLD_SIGNAL_SLOT
  // run application
  return qApp.exec();
}

Header file PushButton.h to override QPushButton for Qt 4:

#ifndef PUSH_BUTTON_H
#define PUSH_BUTTON_H

#include <QPushButton>

class PushButton: public QPushButton {
  Q_OBJECT
  public:
    PushButton(const QString &label, QWidget *pQParent = nullptr):
      QPushButton(label, pQParent)
    { }
  public slots:
    void setDown(bool down) { QPushButton::setDown(down); }
};

#endif // PUSH_BUTTON_H

Note:

Unfortunately, QPushButton::setDown() is not a slot and thus cannot be used as such in Qt 4 like signals. Thus, PushButton is derived from QPushButton only to make setDown() a slot.

I compiled it in VS2013 and tested on Windows 10 (64 bit).

testQPushButtonSetDown的快照(不强制按下按钮)

testQPushButtonSetDown的快照(强制按下按钮)

It seems to work like expected.

I doesn't look like "The button is down." but this his how it's rendered on my Windows 10 where the default Qt style ( "windowsvista" ) mimics the Windows look&feel. At least, you can see a visible change of the button when the check box is toggled. Beside of this, it has the exact look when button is clicked by mouse.


Note:

Calling QPushButton::setDown() does not emit a pressed() or clicked() signal.

From Qt doc. (emphasizing by me):

If this property is true , the button is pressed down. The signals pressed () and clicked () are not emitted if you set this property to true.

If this is intended, you had to use another method instead: QPushButton::click()

This is described in the Qt doc. of QAbstractButton (from which it is inherited in QPushButton ):

QAbstractButton provides four signals:

  1. pressed () is emitted when the left mouse button is pressed while the mouse cursor is inside the button.

  2. released () is emitted when the left mouse button is released.

  3. clicked () is emitted when the button is first pressed and then released, when the shortcut key is typed, or when click () or animateClick () is called.

  4. toggled () is emitted when the state of a toggle button changes.

You can use an EventFilter to drop all mouse press events from this button.

yourButton->installEventFilter(this); // this = MainWindow, change to your needs

bool MainWindow::eventFilter(QObject *obj, QEvent *event)    
{
    if (event->type() == QEvent::MouseButtonPress)
    {
        QPushButton *button = static_cast<QPushButton *>(obj);
        if (button == yourButton)
            if (button->isDown())
                return true;
    }
    // standard event processing
    return QObject::eventFilter(obj, event);
}

After another control set down to false, everthing works as before.

A button must be set checkable to retain its state after losing the focus.

Try setChecked(TRUE) on the button before calling setDown().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM