Unique PlugIn window with pyhton 3dsmax

python
qt
max
#1

Is it possible to destroy a previously loaded QTWidget?
I’m not sure on the way I could get the instance.
In maxscript I have seen that is possible to assign a classID making sure there is no duplication when you run a script/plugin
How can I do this in pyhton?
Thanks

#2

Yes it is possible. Research singleton pattern:
https://www.tutorialspoint.com/python_design_patterns/python_design_patterns_singleton.htm

1 Like
#3

I thought on a design pattern solution as well in a first instance then I saw the class Id solution and I thought was cleaner.
As I cannot find the way to do it in python I’ll go with the singleton pattern as you suggest.
Thanks

#4

This is actually what I’m trying to do:

import os
import sys
import pymxs
rt = pymxs.runtime

from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets
from PySide2.QtUiTools import QUiLoader

dir_path = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(os.path.dirname(dir_path), os.pardir))
sys.path.append(dir_path)


import MaxPlus

class WidgetSkeleton():
    def __init__(self):
        self.main_view = MainView()


class MainView(QtWidgets.QDockWidget):

    def __init__(self):
        super(MainView, self).__init__()
        loader = QUiLoader()
        main_ui_path = os.path.join(os.path.dirname(__file__), "main_view.ui")
        self.ui = loader.load(main_ui_path)
        MaxPlus.GetQMaxMainWindow().addDockWidget(QtCore.Qt.RightDockWidgetArea, self.ui)

    def show(self):
        self.ui.show()


if __name__ == '__main__':
    max_window = MaxPlus.GetQMaxMainWindow()
    skeleton_view = max_window.findChildren(QtWidgets.QDockWidget , "Skeleton")
    for s in skeleton_view:
        max_window.removeDockWidget(s)
    core = WidgetSkeleton()
    core.main_view.show()

This what I’m trying to do actually using a singleton is not the best solution for me actually because python reloads everything when I load my script.

What I need is more something like this:

plugin helper lightMaster
name:"Light Master"
classID:#(12345,54321)
extends:Dummy
replaceUI:true
invisible:true
(

but I don’t know if this is callable from maxplus directly.
The code I posted does what I want but leave a reference when I right click on the dockable area on the right of 3dsmax interface, this because I destroy the UI but not the instance of my class
How could I fix this?
Thanks

#5

this user has the same problem, the image make everything clear

#6

Hey,

So this is how I have solved it for the past 4 or so years:

You need to have a module to hold all of your singleton pointers, let’s call it pointers.py.
In pointers.py you add a variable that is to hold the pointer for your ui:

myUIPointer = None

Then in your main module, let’s call it main.py you have the following:

import pointers
import MaxPlus as mxPy

class myUI(QtWidgets.QDockWidet):

    """ This is my widget """

    def __init__(self):

        super(myUI, self).__init__()
        self.setWindowTitle("My UI")

def define_MyUISingleton(forceLoad=False, displayUI=True):

    # check if the singleton pointer is None or if
    # it should be forcibly redefined.
    # If so create a new instance and assign it:
    if pointers.myUIPointer is None or forceLoad:

        pointers.myUIPointer = myUI()
        # Properly attach the widget to the main max window:
        mxPy.AttachQWidgetToMax(pointers.myUIPointer)

    if displayUI:

        pointers.myUIPointer.show()

    return pointers.myUIPointer

Then in an arbitrary module where you want to access your singleton, let’s call it test.py, you have:

import main

myUI = main.define_MyUISingleton()

And presuming that you never directly delete pointers.myUIPointer with del, the ui will be listed when you right click on any max toolbar as “My UI”, as in the link you posted.
And if you feel really fancy you can add this pointer to maxscript memory for easy access using a predefined maxscript struct and pymxs.runtime.

Excuse any typos, I have written this on my phone.

1 Like
#7

Cool , really thanks.
I’ll try it tomorrow at work
Thanks again

#8

It works perfectly, thanks

#9

Nps, glad I could help