Why alt modifier does not trigger key release event the first time you press it in maya?

473 Views Asked by At

In autodesk maya 2019, I want to capture keypress/release event for keyboard modifiers, but after adding a QPushButton to maya's workspaceControl, Alt key behaves different than other modifiers.

  1. press alt key, keyPress event fires
  2. release alt key, no key release event
  3. press alt key again, no key press event
  4. release alt key again, key release event fires

I was expecting to see respective events in 2 and 3.

import maya.cmds as MC
from maya import OpenMayaUI
import shiboken2
from PySide2 import QtCore, QtGui, QtWidgets
modifierKeyInverseMap = {v: k for k, v in QtCore.Qt.KeyboardModifier.values.items()}


class TestButton(QtWidgets.QPushButton):
    def __init__(self, *args):
        super(TestButton, self).__init__(*args)
        self.installEventFilter(self)

    def eventFilter(self, source, event):
        # print('-', event.type(), event, source)
        def debug():
            for k in modifierKeyInverseMap:
                if k & modifiers:
                    print('-', modifierKeyInverseMap[k])

        if event.type() == QtCore.QEvent.KeyPress:
            print('key press')
            if hasattr(event, 'modifiers'):
                modifiers = event.modifiers()
                debug()

        elif event.type() == QtCore.QEvent.KeyRelease:
            print('key release')
            modifiers = event.modifiers()
            debug()

        elif event.type() == QtCore.QEvent.Enter:
            source.setFocus()


def createUI():
    ptr = OpenMayaUI.MQtUtil.getCurrentParent()
    workspace_control = shiboken2.wrapInstance(long(ptr), QtWidgets.QWidget)
    layout = QtWidgets.QHBoxLayout()
    # workspace control has a vboxlayout placeholder on creation when direction is horizontal
    workspace_control.layout().addLayout(layout)


name = 'test'

if MC.workspaceControl(name, exists=True):
    MC.deleteUI(name)

ctrl = MC.workspaceControl(name, label='test workspace ctrl',
                           loadImmediately=True, uiScript="createUI()",
                           initialHeight=23)

MC.workspaceControl(ctrl, edit=True, dockToControl=['TimeSlider', 'top'])

ptr = OpenMayaUI.MQtUtil.findControl(ctrl)
qctrl = shiboken2.wrapInstance(long(ptr), QtWidgets.QWidget)

qlayout = qctrl.children()[-1].children()[0]

button = TestButton('yeah')
button.setFixedWidth(50)
qlayout.addWidget(button)

horizontalSpacer = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
qlayout.addItem(horizontalSpacer)

I recreated this problem outside maya, by making a qmainwindow with menubar then adding a button to it with eventfilter. If I install event filter to main window, then the alt modifier detection works, but I need granular control for multiple buttons, so I want the eventFilters to be installed onto the button directly.

import os
import sys

from PySide2 import QtCore, QtGui, QtWidgets

modifierKeyInverseMap = {v: k for k, v in QtCore.Qt.KeyboardModifier.values.items()}


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        fileMenu.addAction(QtWidgets.QAction('yeah', self))

        button = QtWidgets.QPushButton('Button')
        self.setCentralWidget(button)
        self.setWindowTitle('test')
        button.installEventFilter(self)

    def eventFilter(self, source, event):
        # print('-', event.type(), event, source)
        def debug():
            for k in modifierKeyInverseMap:
                if k & modifiers:
                    print('-', modifierKeyInverseMap[k])

        if event.type() == QtCore.QEvent.KeyPress:
            print('key press')
            if hasattr(event, 'modifiers'):
                modifiers = event.modifiers()
                debug()

        elif event.type() == QtCore.QEvent.KeyRelease:
            print('key release')
            modifiers = event.modifiers()
            debug()

        elif event.type() == QtCore.QEvent.Enter:
            source.setFocus()


in_maya = False
try:
    import maya.cmds
    in_maya = True
except:
    app = QtWidgets.QApplication(sys.argv)

win = MainWindow()
win.show()

win.raise_()
win.move(500, 500)

if not in_maya:
    sys.exit(app.exec_())

Edit: It seems to be caused by pressing alt key in mainwindow with menubar has the focus moved to File menu the first time alt key is released, then from that moment on, no event filter fires on the button until the focus is back.

0

There are 0 best solutions below