Detecting a key press during command execution

I am trying to detect a key press in the middle of command execution in Python Maya. I first tried a brute-force approach using the QApplication event queue (probably not the optimal way):

class MyEventHandler(QtCore.QObject):

    def eventFilter(self, qobj, event):
        if event.type() == QtCore.QEvent.KeyPress:
            print('key pressed')

        return super(MyEventHandler, self).eventFilter(qobj, event)


class MyCmd(OpenMayaMPx.MPxCommand):

    def __init__(self):
        super().__init__()
        self.maya_window = wrapInstance(int(OpenMayaUI.MQtUtil.mainWindow()), QtWidgets.QWidget)
        self.event_handler = MyEventHandler()
        self.app = QtWidgets.QApplication.instance()
        self.app.installEventFilter(self.event_handler)

    def __del__(self):
        if hasattr(self, 'app'):
            self.app.removeEventFilter(self.event_handler)
    
    def doIt(self, args):
        // do some stuff

        QtWidgets.QApplication.processEvents()

        // do some stuff

So while the command is being executed I see the event handler is being called with various message types but key press events are not detected at all, despite the fact I am pressing keys randomly during command execution. Any ideas why key presses are not being received using the code above?

Or is there a better way of achieving this, without using the application event queue?

Are you interested in a specific key, or any key, or a key modifier (Control, Alt, Shift)?

Are you looking to use it on Windows only or do you need it to work on multiple platforms?

My intention is to catch ESC but I may switch to any other key if it turns out that ESC is problematic due to some reason. Key modifiers are not required.

Eventually the code should work on all platforms which are supported by Maya but I will consider a Windows-specific solution as well if there is no other option.

using MProgressWindow is not a solution?

1 Like

Yes, it is for my particular use case! I am new to Maya so I didn’t know about it - thank you!

That being said I think that ability track any key presses still may useful for more complex use cases so I leave the question open. Knowing how to do that would be very desirable.

Detecting any keystroke is system dependent.
As far as I know, the keyboard or win32api modules are not part of the default package, and there is no built-in python module for this.

I understand. But what about Qt which is system-independent? Do you have an idea why it doesn’t detect any keystroke?

Because Qt is cross-platform, each system requires different key handling. However, modifier keys are unified. If you only need the Ctrl, Alt, and Shift keys, this can be easily implemented with Qt.

1 Like

If the goal is not to interrupt script execution, or Detecting Modifier Keys, then, first of all, the question arises - WHY!?
There are hardly any simple solutions.
Basically, these are “dirty clumsy crutches”, and platform-dependent ones at that.
Something like running tkinter/keyboard in a parallel thread and trying to pass information between threads…
If the target is to Detecting Escape then you can use MPxContext:
OpenMayaUI.MPxContext.abortAction()
OpenMayaUI.MPxContext

If you decide to use progressWindow, then it makes sense to do the implementation in the with context.
Something like this:
How can I author a progressWindow context manager?

NB:
Your code works.
But it detects keypresses in the main thread.
If you want to detect keystrokes in other threads, then you will need to take special care of this.
The Maya API provides rich capabilities for detecting mouse button presses, cursor movements, and modifier key presses.
Be careful when overriding keypress behavior.
It’s very easy to break Maya’s built-in Hotkey system. Especially if the user has added or reassigned something.

1 Like

I understand. Thank you all for answers :slight_smile:

Worth asking here actually;
A while ago I wrote an app agnostic publishing tool and needed the same thing - pressing esc at any point to cancel the process.
I didn’t want to implement different key overrides per DCC (or standalone).
Instead, I used keyboard which worked beautifully.

Would anyone recommend otherwise?

Using the keyboard module is the first thing that comes to mind, and it should work fine on Windows and Linux, but…
It’s not a standard module, and it requires a special installation for clients.
Within your own pipeline (internal project) - this is definitely one of the best solutions.

1 Like