2011-04-12 11 views
5

Estoy escribiendo una aplicación si uso mi propio atajo. Se ve así:Conflicto QShortCut y QSpinBox

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

he definido en el constructor del widget de principal y funciona bien hasta que haga clic en uno de los botones del selector numérico que también se encuentran en el widget principal. Después de eso, mi atajo deja de funcionar y no funciona hasta que hago clic en el botón o en la casilla de verificación. Cuando hago eso todo está bien nuevamente. Me gustaría añadir que después de hacer clic en el cuadro de giro parece estar "activo" (porque el cursor aún "parpadea") hasta que hago clic en uno de los otros botones. ¿Tienes alguna idea de lo que está mal? ¿Es algún tipo de proceso o problema de evento? Gracias por todas las respuestas ~ Marwroc

Respuesta

4

Un acceso directo es "escuchó" por el bucle evento de Qt cuando widget padre del acceso directo está recibiendo eventos.

Cuando QSpinBox tiene keyboard focus, el padre del objeto QShortcut ya no recibe eventos. Por lo tanto, el acceso directo no funciona hasta que keyboard focus se elimine del QSpinBox. Puede cambiar este comportamiento pasando Qt::WidgetWithChildrenShortcut or Qt::ApplicationShortcut al método QShortcut::setContext de su QShortcut.

+0

Gracias por su respuesta. ¿Tienes alguna idea de cómo resolver este problema? Me refiero a cómo eliminar keyboard_focus automáticamente de QSpinBox después de cada "clic"? – Marwroc

+0

@Marwroc Actualicé la respuesta. ¿Has probado 'QShortcut :: setContext' aún? –

+0

Sí, he probado ambas opciones, pero todavía no funciona;/He leído algo sobre setFocusPolicy() pero no estoy seguro de cómo usarlo y si es la solución. – Marwroc

1

¿Has probado MySpinBox -> setFocusPolicy (Qt::NoFocus)?

+0

Gracias, funciona, pero ahora el problema es que no puedo escribir nada en QSpinBox simplemente haga clic. El rango de mi QSpinBox es de 0 a 500, por lo que es muy necesario escribir;/​​ – Marwroc

+0

Encontré la solución. Usé setFocusPolicy (Qt :: ClickFocus) en main_widget y ahora funciona bien. Una vez más, gracias por tu ayuda;) – Marwroc

2

Antes de activar un atajo, el widget de enfoque recibe un evento ShortcutOverride. Si se acepta el evento, el evento clave se transfiere al widget y el acceso directo no se activa.

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

En cuanto a la fuente 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 es permitir la edición interno para aceptar el caso. QLineEdit se remite a QLineControl. De 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; 
       } 
      } 
     } 
    } 

Este código acepta la mayoría de las llaves si no está también presionó la tecla de control.

Así que la solución más fácil es cambiar el atajo para incluir el modificador de control.

Como alternativa, puede subclase el cuadro de giro y anular la función de eventos

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); 
}