I'm writing an application were i use my own shortcut. It looks like this:
myShortcut= new QShortcut(Qt::SHIFT + Qt::Key_B,this);
connect(myShortcut, SIGNAL(activated()), this, SLOT(setCameraBack()));
I defined it in the constructor of main widget and it works fine until i click one of the spinbox buttons which are also located on the main widget. After that my shortcut stop working and it doesn't work until i click push button or check box. When i do that everything is fine again. I'd like to add that after i click spinbox it seems to be "active" (because the cursor is still "blinking" on it) until i click one of the other buttons. Do you have any idea what is wrong? Is it some kind process or event problem? Thanks for all answers ~Marwroc
A shortcut is "listened for" by Qt's event loop when the shortcut's parent widget is receiving events.
When the QSpinBox has keyboard focus, then the QShortcut object's parent is no longer receiving events. Therefore, the shortcut does not work until keyboard focus is removed form the QSpinBox. You can change this behavior by passing Qt::WidgetWithChildrenShortcut or Qt::ApplicationShortcut to the QShortcut::setContext method of your QShortcut.
Before a shortcut is activated, the focus widget is given a ShortcutOverride event. If the event is accepted, the key event is passed along to the widget and the shortcut is not activated.
Source: https://wiki.qt.io/ShortcutOverride
Looking at Qt source
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 is allowing the internal edit to accept the event. QLineEdit defers to QLineControl. From qt/src/gui/widgets/qlinecontrol.cpp
case QEvent::ShortcutOverride:{
if (isReadOnly())
return false;
QKeyEvent* ke = static_cast<QKeyEvent*>(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;
}
}
}
}
This code accepts most keys if the control key is not also pressed.
So the easiest solution is to change the shortcut to include the control modifier.
Alternatively, you can subclass the spin box and override the event function
bool MySpinBox::event(QEvent *event)
{
if( event->type() == QEvent::ShortcutOverride && !isReadOnly() )
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
// Ignore 'B' shortcuts
if( keyEvent->key() == Qt::Key_B )
{
Q_ASSERT( !event->isAccepted() );
return true;
}
return QSpinBox::event(event);
}
Have you tried MySpinBox -> setFocusPolicy (Qt::NoFocus)
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With