Frage

Extraneous Information: I am attempting to build an application using Qt. This application features a QMdiArea and a child-window. My child-window will have a menu which can be integrated into the QMdiArea or segregated and attached to the child itself. Though, this is a bit more detail than needed...

Problem: I would like my child-widget to have a menu with a shortcut, "CTRL+W." But, because I am using a QMdiArea, the shortcut is already used causing:

QAction::eventFilter: Ambiguous shortcut overload: Ctrl+W

How can I get rid of this shortcut and claim it within my child widget instead?

Update: Here is what I've tried with no luck:

class MDI : public QMdiArea
{
    Q_OBJECT
    private:
    bool event(QEvent *tEvent)
    {
        if (tEvent->type() == QEvent::KeyPress)
        {
            QKeyEvent* ke = static_cast<QKeyEvent*>(tEvent);
            if (ke->key()== Qt::Key_W && ke->modifiers() & Qt::ControlModifier)
            emit KeyCW();
            return true;
        }
        return QMdiArea::event(tEvent);
    }
public:
signals:
    void KeyCW();
};

This works if I do something as simple as change Qt::Key_W to Qt::Key_L. The key-combo is received and event is thrown. With W, it just never happens. I've also tried moving event to QMainWindow as well as an eventFilter in the subwindow to QMdiArea. It seems that it is a little overly complicated to do something as simple as remove default key-handlers from within QMdiArea.

War es hilfreich?

Lösung 4

From what I can tell, what I am looking for is not possible short of writing my own MDIArea.

The shortcut is set in QMdiSubWindowPrivate::createSystemMenu() during the construction of a QMdiSubWindow, I doubt that you can remove it without having to patch Qt libs.

Hopefully at some point someone will disprove this or QT will make changes. Meanwhile, it looks like we will all need to stay away from these pre-assigned shortcuts.

Andere Tipps

You can disable this shortcut like this:

for( QAction *action : subWindow->systemMenu()->actions() ) {
    if( action->shortcut() == QKeySequence( QKeySequence::Close ) ) {
        action->setShortcut( QKeySequence() );
        break;
    }
}

You could get rid of the pre-defined close action of the QMdiSubWindow altogether by using Qt::CustomizeWindowHint as additional flag when adding the subwindow.

QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(internalWidget2, 
                                                 Qt::Widget | Qt::CustomizeWindowHint | 
                                                 Qt::WindowMinMaxButtonsHint);

Subclass QMdiArea and reimplement keyPressEvent(). That should work.

  void keyPressEvent(QKeyEvent* event){

    if(event->key() == Qt::Key_W and event->modifiers() & Qt::ControlModifier){
      // handle it
    }else{
      return QMdiArea::keyPressEvent(event);
    }
  }

You could also use event filters. I don't enough about your class hierarchy, but I hope you get the idea.

bool CustomMdiArea::eventFilter(QObject *object, QEvent *event){
     if(object == yourChildWindow && event->type() == QEvent::KeyPress) {
         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
         if(keyEvent->key() == Qt::Key_W and keyEvent->modifiers() & Qt::ControlModifier) {
             //handle it
             return true;
         }else{
             return false;
         }
     }
     return false;
 }

I was able to work around this by setting the shortcut context for my close action. By setting it to Qt::WidgetShortcut, I no longer get the ambiguous shortcut overload. Here is how I'm setting up my close action now:

  closeAction = new QAction(tr("&Close"), this);
  closeAction->setShortcut(Qt::CTRL|Qt::Key_W);
  closeAction->setShortcutContext(Qt::WidgetShortcut);
  connect(closeAction, SIGNAL(triggered()), mdiArea, SLOT(closeActiveSubWindow()));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top