1

I'm trying to get Maya's log(What it prints in script editor's output window) and add it to my custom PySide Qwidget. Why this crashes Maya

QtWidgets, QtCore, QtGui
imoprt QtDesiner_UI
import maya.OpenMayaUI as OmUi
from shiboken2 import wrapInstance
import maya.OpenMaya as Om

def get_maya_window():
    # Get Maya window
    maya_main_window_ptr = OMUI.MQtUtil.mainWindow()

    maya_main_window = wrapInstance(long(maya_main_window_ptr), 
    QtWidgets.QMainWindow)

    return maya_main_window

class UiClass(QtWidgets.QMainWindow, QtDesiner_UI.MainWindow):

    def __init__(self):
        super(UiClass, self).__init__(get_maya_window())

        OM.MCommandMessage.addCommandOutputFilterCallback(self.callback)
        # some PySide Widgets here
        self.console_widget = QtWidgets.QTextEdit()
        self.main_form_layout.addRow(self.console_widget)

    def callback(self, msg, mg, *args):
       self.console_widget.append(msg)

    def logic_stuff(self):
        #maya commands here

import UI_Window
w = UI_Window.UiClass()
w.show()

And this doesn't

def callback(msg, mg ,*args):
    console_widget.append(var)

OM.MCommandMessage.addCommandOutputFilterCallback(callback)

Here is the the working code that works partially. It should append log info into 'QtextEdit()' but after first operation Maya crashes(e.g. create sphere).

import maya.OpenMayaUI as OmUi
from shiboken2 import wrapInstance
from PySide2 import QtWidgets, QtCore, QtGui
import maya.OpenMaya as Om

def get_maya_window():
    # Get Maya window
    maya_main_window_ptr = OmUi.MQtUtil.mainWindow()
    maya_main_window = wrapInstance(long(maya_main_window_ptr), QtWidgets.QMainWindow)
    return maya_main_window

class MainWidget(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWidget, self).__init__(get_maya_window())

        self.cent_ly = MW()
        self.text_edit = QtWidgets.QTextEdit()
        self.cent_ly.vlayout.addWidget(self.text_edit )
        self.setCentralWidget(self.cent_ly )

        self.callback_id = Om.MCommandMessage.addCommandOutputFilterCallback(self.callback)

    def closeEvent(self, event):
        Om.MMessage.removeCallback(self.callback_id)

    def callback(self, message):
        self.text_edit.append(message.strip())

class MW(QtWidgets.QWidget):
    def __init__(self):
        super(MW , self).__init__()
        self.vlayout = QtWidgets.QVBoxLayout()        
        self.setLayout(self.vlayout)

w = MainWidget()
w.show()

And this one works without crashing Maya

import maya.OpenMayaUI as OmUi
from shiboken2 import wrapInstance
from PySide2 import QtWidgets, QtCore, QtGui
import maya.OpenMaya as Om

def get_maya_window():
    # Get Maya window
    maya_main_window_ptr = OmUi.MQtUtil.mainWindow()
    maya_main_window = wrapInstance(long(maya_main_window_ptr), QtWidgets.QMainWindow)
    return maya_main_window

class MainWidget(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWidget, self).__init__(get_maya_window())

        self.cent_ly = MW()
        self.text_edit = QtWidgets.QTextEdit()
        self.cent_ly.vlayout.addWidget(self.text_edit)
        self.setCentralWidget(self.cent_ly )

class MW(QtWidgets.QWidget):
    def __init__(self):
        super(MW , self).__init__()
        self.vlayout = QtWidgets.QVBoxLayout()        
        self.setLayout(self.vlayout)

w = MainWidget()
w.show()

def callback(message,  *args):
    w.text_edit.append(message.strip())

callback_id = Om.MCommandMessage.addCommandOutputFilterCallback(callback)

# Om.MMessage.removeCallback(callback_id)
IKA
  • 151
  • 1
  • 3
  • 11

2 Answers2

3

You need to remove the callback when you close the window. I was testing your code and it worked the first time, but subsequent times froze Maya.

class UiClass(QtWidgets.QMainWindow):
    def __init__(self):
        super(UiClass, self).__init__(get_maya_window())
        self.callback_id = Om.MCommandMessage.addCommandOutputFilterCallback(self.callback)

    def closeEvent(self, event):
        Om.MMessage.removeCallback(self.callback_id)

Like @ababak said, the crashes happen because the object was destroyed, which happens when you close the window. So before that happens, you need to remove the callback.

meepzh
  • 707
  • 1
  • 7
  • 15
  • Thanks it solved partially the problem now it crashes Maya after you do some operation that generates message. E.g. create locator or select some nodes in the viewport. – IKA Apr 05 '20 at 14:46
  • @iRex That could be a previous window that has already been destroyed but still was subscribed for the callback. – ababak Apr 05 '20 at 14:48
  • @ababak how it is possible if I'm calling it only once? – IKA Apr 05 '20 at 14:57
2

You haven't shown the complete code of the first sample.

Those crashes happen when the callback is fired up but the original object has already been destroyed.

I assume you create the UiClass object but later it is garbage collected. The second sample does not crash as you define your callback function in a global scope and it stays valid until you quit Maya.

IKA
  • 151
  • 1
  • 3
  • 11
ababak
  • 1,685
  • 1
  • 11
  • 23
  • Sorry I can't post whole code but I have added some lines to show general purpose of the code. I have UI that needs to be updated. How to avoid garbage collection? – IKA Apr 05 '20 at 11:50
  • Sorry, even after you added some code to your question I still don't see where you create the `UiClass` object. – ababak Apr 05 '20 at 13:47
  • I'm sorry it was misunderstood. I have added the lines. First I import the module. Then I create the object and call it with `show()` – IKA Apr 05 '20 at 14:19