简体   繁体   中英

Why QAbstractButton emit all signals when using keyboard navigation?

I have a couple of custom buttons derived from QAbstractButton with autoExclusive and checkable property TRUE witch are applied to the same parent.(so the only one item can be checked at the same time).

The parent is a QDialog and i want whenever the dialog is displayed for example item 1 get keyboard focus so the user can easily navigate between items from keyboard BUT trigger some function only if user choose an item with mouse release.

When i catch the signals on keyboard navigation (for item 2 in this case) all QAbstractButton signals:

clicked

pressed

released

toggled

will be triggered.

Why this happen ?

What can i do?

Item and Dialog implementation:

Item::Item(QWidget *parent) : QAbstractButton(parent) {
    setAutoExclusive(true);
    setCheckable(true);
}

void Item::paintEvent(QPaintEvent *) {
    QPainter p(this);
    p.setPen(Qt::NoPen);
    p.setRenderHint(QPainter::Antialiasing);
    p.setBrush(/*brush*/);
    p.drawRoundedRect(rect(), /* raduis*/, /* radius */);
    p.setRenderHint(QPainter::Antialiasing, false);

    if (isChecked()) p.drawPixmap(rect(), /*pixmap*/);
}

QSize Item::sizeHint() const {
    return QSize(/*size*/, /*size*/);
}

Dialog::Dialog(QWidget *parent) : QDialog(parent) {
    _mainLayout.setContentsMargins(24, 24, 24, 24);
    _mainLayout.setSpacing(12);

    _mainLayout.addWidget(&_item1, 0, 0);
    _mainLayout.addWidget(&_item2, 0, 1);
    _mainLayout.addWidget(&_item3, 0, 2);

    QObject::connect(&_item2, SIGNAL(clicked()), this, SLOT(onItemClicked()));
    QObject::connect(&_item2, SIGNAL(released()), this, SLOT(onItemReleased()));
    QObject::connect(&_item2, SIGNAL(pressed()), this, SLOT(onItemPPress()));
    QObject::connect(&_item2, SIGNAL(toggled(bool)), this, SLOT(onToggle(bool)));
}

void Dialog::showEvent(QShowEvent *e) {
    _item1.setFocus(Qt::TabFocusReason);
    QDialog::showEvent(e);
}

void Dialog::onItemClicked() {
        qDebug() << "CLICKED";
}
void Dialog::onItemReleased() {
        qDebug() << "RELEASED";
}
void Dialog::onItemPPress() {
        qDebug() << "PRESS";
}
void Dialog::onToggle(bool f) {
        qDebug() << "Toggle";
}

Why [does] this [sending of signals] happen ?

Because typically an application isn't going to care how the button was activated, only that it was activated. If Qt did not emit those signals in response to keypress events, people would be forever complaining that their buttons weren't emitting the expected signals when someone manipulated them via the keyboard, and every developer would then have to manually add their own keyboard-support logic to every button to get the expected behavior.

What can i do?

The first thing to do is consider whether you really want to break keyboard support in your app. Most people will expect to be able to activate buttons using the keyboard, and people who are unable to use a mouse (eg because they are blind and using screen-navigation software, or because their mouse isn't currently plugged in) will be unable to close your dialog if you disable keyboard support.

Assuming you've considered that and want to go ahead anyway, I believe you can capture the keystrokes by overriding keyPressEvent(QKeyEvent *) in your button subclasses. Your subclass implementation can check to see if the QKeyEvent that is passed in to it represents one of the offending keystrokes, and if it does, it can just call accept() on the QKeyEvent object (and do nothing else) rather than passing the keyPressEvent() call up to the superclass.

Alternatively, you could just call setFocusPolicy(Qt::NoFocus) on your button widgets, which would prevent them from ever getting the focus, which would in turn prevent them from ever receiving keystrokes.

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