Search code examples
pythonpyqtpysidemaya

How to inherit QtWidgets.QWidget in my class and make my class type - QtWidgets.QWidget?


I am trying to make some code in Maya, I am sorry if it will cause any confuse in my script example below. Problem is that I want to make my custom PyQt class which will later used as Widget in my Layout, but my lack of knowledge in this thing , causing error

# RuntimeError: '__init__' method of object's base class (test) not called. # 

I read few topics about that error and people suggest to fix it with super(). I tried to put "super()" , then I am getting this error :

# TypeError: PySide2.QtCore.QObject isn't a direct base class of test #

Can somebody clear this thing for me ?

from PySide2 import QtGui, QtCore, QtWidgets
from shiboken2 import wrapInstance
import maya.OpenMaya as om
import maya.OpenMayaUI as omui
import maya.cmds as cmds
import os, functools


def getMayaWindow():
    pointer = omui.MQtUtil.mainWindow()
    if pointer is not None:
        return wrapInstance(long(pointer), QtWidgets.QWidget)

class testUi():
    def __init__(self):
        self.window = 'vl_test'
        self.title = 'Test Remastered'
        self.size = (1000, 650)

    def create(self):
        if cmds.window(self.window, exists=True):
            cmds.deleteUI(self.window, window=True)

        self.parentWindow = getMayaWindow()
        self.mainWindow = QtWidgets.QMainWindow(self.parentWindow)
        self.mainWindow.setObjectName(self.window)
        self.mainWindow.setWindowTitle(self.title)

        self.mainWidget = QtWidgets.QWidget()
        self.mainWindow.setCentralWidget(self.mainWidget)
        self.mainLayout = QtWidgets.QFormLayout(self.mainWidget)
        testik = test(self)
        self.mainLayout.addWidget(testik)

        self.mainButton = QtWidgets.QPushButton()
        self.mainLayout.addWidget(self.mainButton)
        self.mainButton.clicked.connect(partial(self.load_selected))


class test(QtWidgets.QWidget):
    def __init__(self, parent=None, maya_transform_nodes=[]):
        #super(QtWidgets.QWidget, self ).__init__(parent)
        qWid = QtWidgets.QWidget()
        self.setMinW = qWid.setMinimumWidth(300)
        self.setMinH = qWid.setMinimumHeight(300)
        self.sss = qWid.setStyleSheet("border:1px solid rgb(0, 255, 0); ")
        self.items = []

        self.transform_move = QtGui.QTransform()
        self.transform_scale = QtGui.QTransform()

        self.prev_mouse_pos = QtCore.QPoint(0, 0)

        self.color = QtGui.QColor(0, 255, 50, 50)
        self.clicked_color = QtGui.QColor(0, 255, 50, 150)
        self.right_clicked_color = QtGui.QColor(255, 0, 0, 150)

v = testUi()
v.create()

Solution

  • When you create a class you have an option to inherit from another object, in this case probably a QDialog since it's your tool's main window. It's not enough to simply inherit it though, you have to call QDialog's constructor in order for it to initialize properly, and you can do that with super.

    With super you can choose to run a method from your class's object it inherited from. It will look something like this: super(YOUR_CLASS_NAME, INSTANCE).METHOD_TO_RUN(PARAMETERS_TO_PASS). So more specifically to run your __init__ it will be: super(testUi, self).__init__(parent), and that will fix it.

    That was probably an awful explanation so please Google super for much better examples.

    I did some edits to your script to simplify it and left some comments in it:

    from PySide2 import QtGui, QtCore, QtWidgets
    from shiboken2 import wrapInstance
    import maya.OpenMaya as om
    import maya.OpenMayaUI as omui
    import maya.cmds as cmds
    import os, functools
    
    
    def getMayaWindow():
        pointer = omui.MQtUtil.mainWindow()
        if pointer is not None:
            return wrapInstance(long(pointer), QtWidgets.QWidget)
    
    
    class testUi(QtWidgets.QDialog):  # Need to inherit from a `QObject`
    
        def __init__(self, parent=None):  # It's typical to include the `parent` parameter and pass that through `super`.
            # If nothing was passed for parent, default to Maya's main window.
            if parent is None:
                parent = getMayaWindow()
    
            super(testUi, self).__init__(parent)  # Call `super` with the class's name, testUi, and its instance, self.
            self.window = 'vl_test'
            self.title = 'Test Remastered'
            self.size = (1000, 650)
    
            self.create()  # Just automatically call create in the instance's constructor.
    
        def create(self):
            if cmds.window(self.window, exists=True):
                cmds.deleteUI(self.window, window=True)
    
            self.setWindowTitle(self.title)
            self.resize(QtCore.QSize(*self.size))
    
            self.testik = test(self)  # Add `self.` so it belongs to this instance.
    
            self.mainButton = QtWidgets.QPushButton()
    
            self.mainLayout = QtWidgets.QVBoxLayout()  # QVBoxLayout seems to give a better result.
            self.mainLayout.addWidget(self.testik)
            self.mainLayout.addWidget(self.mainButton)
            self.setLayout(self.mainLayout)  # Don't forget to make this widget actually set to this layout and use it.
    
    
    class test(QtWidgets.QFrame):
    
        def __init__(self, parent=None, maya_transform_nodes=[]):
            super(test, self).__init__(parent)  # Call `super` with the class's name, test, and its instance, self.
    
            self.setMinimumWidth(300)
            self.setMinimumHeight(300)
            self.setStyleSheet("QWidget {border: 1px solid rgb(0, 255, 0)};")
    
            self.items = []
    
            self.transform_move = QtGui.QTransform()
            self.transform_scale = QtGui.QTransform()
    
            self.prev_mouse_pos = QtCore.QPoint(0, 0)
    
            self.color = QtGui.QColor(0, 255, 50, 50)
            self.clicked_color = QtGui.QColor(0, 255, 50, 150)
            self.right_clicked_color = QtGui.QColor(255, 0, 0, 150)
    
    
    v = testUi()
    v.show()  # Call show to show it!
    

    Am I right to assume you're trying to build a synoptics? If yes, you might want to check out QGraphicsView to populate a window with items and to handle most of the logic. Otherwise you will have to do it 100% yourself, which could be lots of fun, but lots of extra work.