Adding a Menu Bar using PyQt / PySide2


#1

Hi guys,

Been trying a various alternatives but can’t manage to get things working. What I am trying to do is add a Menu Bar to my window using Qt (Python). I have attached an example of my code below. Any tips / advise would be greatly appreciated. Thanks in advance.

# ===============================
# I M P O R T    M O D U L U E S
# ===============================
import maya.OpenMayaUI as omui

# for Maya 2018+...
try:
  
  from PySide2.QtCore import *
  from PySide2.QtGui import *
  from PySide2.QtWidgets import *
  from PySide2 import __version__
  from shiboken2 import wrapInstance 

# for older versions of Maya...
except ImportError:
  
  from PySide.QtCore import * 
  from PySide.QtGui import * 
  from PySide import __version__
  from shiboken import wrapInstance

# ==========
# C L A S S
# ==========
class Test_UI(QWidget):
    
    def __init__(self, *args, **kwargs):
        
        super(Test_UI, self).__init__(*args, **kwargs)
        
        self.setParent(self.GetMainWindow())
        self.setWindowFlags(Qt.Window)
        
        self.setObjectName('Test_UI_uniqueId')
        self.setWindowTitle('Test User Interface')
        self.setGeometry(50, 50, 280, 150)
        self.initUI()
        
    def GetMainWindow(self):
        
        ptr = omui.MQtUtil.mainWindow()
        mainWindow = wrapInstance(long(ptr), QWidget)
        
        return mainWindow
        
    def initUI(self):
        
        self.layout = QGridLayout()
        self.setLayout(self.layout)
        
        self.menuBar = QMenuBar()
        self.menu = QMenu()
        self.menuBar.addMenu(self.menu)
        
        self.text = QLabel()
        self.text.setText("Test Window")
        self.text.setAlignment(Qt.AlignCenter)
        
        self.layout.addWidget(self.menuBar, 0, 0, 1, 1)
        self.layout.addWidget(self.text, 0, 0, 1, 1)
        
if __name__ == "__main__":
    
    Test_UI(Test_UI().GetMainWindow()).show() # show UI

#2

You probably want to specify a parent for your menuBar, self.menuBar = QMenuBar(self).
Probably also true for the rest of the sub objects. They are possibly getting garbage collected as nothing is being told to keep them alive.


#3

Thanks for the prompt reply, R.White.

Apologies for the confusion but what do you mean ‘specify a parent’? How would I go about doing that?


#4

image
QMenuBar takes a parent as an argument in its constructor.

https://doc.qt.io/qtforpython/PySide2/QtWidgets/QMenuBar.html


#5

This is also rather wasteful, as you’re building a whole instance of your UI just to get the main window.

Probably better to just define GetMainWindow as a stand alone function. Plus you can reuse it for future GUIs.


#6

Thanks for pointing me in the proper direction, Katz and R.White. I think I finally got something that works. R.White–you’re completely right. Much better now.

I appreciate all the help. Let me know if there is anything else that stands out.

# ===============================
# I M P O R T    M O D U L U E S
# ===============================
import maya.OpenMayaUI as omui

# for Maya 2018+...
try:
  
  from PySide2.QtCore import *
  from PySide2.QtGui import *
  from PySide2.QtWidgets import *
  from PySide2 import __version__
  from shiboken2 import wrapInstance 

# for older versions of Maya...
except ImportError:
  
  from PySide.QtCore import * 
  from PySide.QtGui import * 
  from PySide import __version__
  from shiboken import wrapInstance

# ==========
# C L A S S
# ==========
class Test_UI(QWidget):
    
    def __init__(self, *args, **kwargs):
        
        super(Test_UI, self).__init__(*args, **kwargs)
        
        self.setParent(self.GetMainWindow())
        self.setWindowFlags(Qt.Window)
        
        self.setObjectName('Test_UI_uniqueId')
        self.setWindowTitle('Test User Interface')
        self.setGeometry(50, 50, 280, 150)
        self.initUI()
        
    def GetMainWindow(self):
        
        ptr = omui.MQtUtil.mainWindow()
        mainWindow = wrapInstance(long(ptr), QWidget)
        
        return mainWindow
        
    def initUI(self):
        
        self.layout = QGridLayout(self)
        self.setLayout(self.layout)
        
        self.menuBar = QMenuBar(parent = self.GetMainWindow()) # requires parent
        self.menu = QMenu(self)
        self.menu.setTitle("Menu")
        self.menuBar.addMenu(self.menu)
        self.menu.addAction("Menu Item")
        self.menu.triggered[QAction].connect(self.MenuAction)
        
        self.text = QLabel(self)
        self.text.setText("Test Window")
        self.text.setAlignment(Qt.AlignCenter)
        
        self.layout.addWidget(self.menuBar, 0, 0, 1, 1)
        self.layout.addWidget(self.text, 0, 0, 1, 1)
        
    def MenuAction(self):
        print("Menu Works.")
        
if __name__ == "__main__":
    
    Test_UI().show() # show UI