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.
- press alt key, keyPress event fires
- release alt key, no key release event
- press alt key again, no key press event
- 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.