5 votes

QShortCut et QSpinBox entrent en conflit

Je suis en train d'écrire une application où j'utilise mes propres raccourcis. Ça ressemble à ça :

myShortcut= new QShortcut(Qt::SHIFT + Qt::Key_B, this);
connect(myShortcut, SIGNAL(activated()), this, SLOT(setCameraBack()));

Je l'ai défini dans le constructeur du widget principal et tout fonctionne bien jusqu'à ce que je clique sur l'un des boutons spinbox qui sont également situés sur le widget principal. Après cela, mon raccourci cesse de fonctionner et ne fonctionne pas tant que je ne clique pas sur un bouton poussoir ou une case à cocher. Lorsque je le fais, tout redevient normal. J'ajouterais qu'après avoir cliqué sur la spinbox, elle semble être "active" (car le curseur continue de "clignoter" dessus) jusqu'à ce que je clique sur l'un des autres boutons. Avez-vous une idée de ce qui ne va pas ? S'agit-il d'un problème de processus ou d'événement ? Merci pour toutes les réponses ~Marwroc

4voto

Judge Maygarden Points 14964

Un raccourci est "écouté" par la boucle d'événements de Qt lorsque le widget parent du raccourci reçoit des événements.

Lorsque le QSpinBox a le focus clavier, alors le parent de l'objet QShortcut ne reçoit plus d'événements. Par conséquent, le raccourci ne fonctionne pas tant que le focus clavier n'est pas retiré du QSpinBox. Vous pouvez modifier ce comportement en passant Qt::WidgetWithChildrenShortcut ou Qt::ApplicationShortcut à la méthode QShortcut::setContext de votre QShortcut.

2voto

Jason Scott Points 51

Avant qu'un raccourci ne soit activé, le widget de focus reçoit un événement ShortcutOverride. Si l'événement est accepté, l'événement clé est transmis au widget et le raccourci n'est pas activé.

Source : https://wiki.qt.io/ShortcutOverride

En examinant la source de Qt

QAbstractSpinBox::event(QEvent *event)
{
    Q_D(QAbstractSpinBox);
    switch (event->type()) {
    ...
    case QEvent::ShortcutOverride:
        if (d->edit->event(event))
            return true;
        break;
    ...
    }
    return QWidget::event(event);
}

QAbstractSpinBox permet à l'éditeur interne d'accepter l'événement. QLineEdit renvoie à QLineControl. Depuis qt/src/gui/widgets/qlinecontrol.cpp

    case QEvent::ShortcutOverride:{
        if (isReadOnly())
            return false;
        QKeyEvent* ke = static_cast(ev);
        if (ke == QKeySequence::Copy
            || ke == QKeySequence::Paste
            || ke == QKeySequence::Cut
            || ke == QKeySequence::Redo
            || ke == QKeySequence::Undo
            || ke == QKeySequence::MoveToNextWord
            || ke == QKeySequence::MoveToPreviousWord
            || ke == QKeySequence::MoveToStartOfDocument
            || ke == QKeySequence::MoveToEndOfDocument
            || ke == QKeySequence::SelectNextWord
            || ke == QKeySequence::SelectPreviousWord
            || ke == QKeySequence::SelectStartOfLine
            || ke == QKeySequence::SelectEndOfLine
            || ke == QKeySequence::SelectStartOfBlock
            || ke == QKeySequence::SelectEndOfBlock
            || ke == QKeySequence::SelectStartOfDocument
            || ke == QKeySequence::SelectAll
            || ke == QKeySequence::SelectEndOfDocument) {
            ke->accept();
        } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
                   || ke->modifiers() == Qt::KeypadModifier) {
            if (ke->key() < Qt::Key_Escape) {
                ke->accept();
            } else {
                switch (ke->key()) {
                case Qt::Key_Delete:
                case Qt::Key_Home:
                case Qt::Key_End:
                case Qt::Key_Backspace:
                case Qt::Key_Left:
                case Qt::Key_Right:
                    ke->accept();
                default:
                    break;
                }
            }
        }
    }

Ce code accepte la plupart des touches si la touche de contrôle n'est pas également enfoncée.

La solution la plus simple est donc de modifier le raccourci pour inclure le modificateur de contrôle.

Alternativement, vous pouvez sous-classer le spin box et remplacer la fonction event

bool MySpinBox::event(QEvent *event)
{
    if( event->type() == QEvent::ShortcutOverride && !isReadOnly() )
    {
        QKeyEvent *keyEvent = static_cast(event);
        // Ignorer les raccourcis 'B'
        if( keyEvent->key() == Qt::Key_B )
        {
            Q_ASSERT( !event->isAccepted() );
            return true;
    }
    return QSpinBox::event(event);
}

1voto

TonyK Points 8604

Avez-vous essayé MySpinBox -> setFocusPolicy(Qt::NoFocus) ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X