Remove tab from tabwidget containing listview and model

792 views
Skip to first unread message

johan Borgström

unread,
Oct 9, 2016, 8:42:33 AM10/9/16
to Python Programming for Autodesk Maya
Hi,

I am using a tabwidget and on each tab I am creating a listview with a standard model. My question is how do I make sure when I delete the tabs that everything gets deleted, including the model. As far as I understand if you delete the parent widget the children will also be deleted.

Below you will find a simplified version of what I am creating. Should I "manually" deleting the model?

Thankful for all comments and feedback!

BR,
Johan

import sys
from PySide2 import QtGui, QtCore, QtWidgets
from maya import OpenMayaUI as omui
from shiboken2 import wrapInstance
from functools import partial


class TabWidget(QtWidgets.QWidget):
    
    def __init__(self, parent=None):
        super(TabWidget, self).__init__(parent) 

        self.setWindowFlags(QtCore.Qt.Tool)
        self.setGeometry(50, 200, 300, 300)
        self.setWindowTitle('Tabwidget')

        vbox = QtWidgets.QVBoxLayout(self)

        self.tab_widget = QtWidgets.QTabWidget()
        vbox.addWidget(self.tab_widget)

        label_list = ['A', 'B', 'C']

        # add tabs
        add_tabs_button = QtWidgets.QPushButton('Add Tabs')
        add_tabs_button.clicked.connect(partial(self.add_tabs, label_list))
        vbox.addWidget(add_tabs_button)

        # remove tabs
        remove_tabs_button = QtWidgets.QPushButton('Remove Tabs')
        remove_tabs_button.clicked.connect(self.remove_tabs)
        vbox.addWidget(remove_tabs_button)

    def remove_tabs(self):
        #self.tab_widget.clear()
        for i in range(self.tab_widget.count()):
            #print self.tab_widget.removeTab(0)
            self.tab_widget.widget(i).deleteLater()

    def add_tabs(self, label_list):

        for label in label_list:

            widget = QtWidgets.QWidget()
            self.tab_widget.addTab(widget, label)
            vbox = QtWidgets.QVBoxLayout(widget)

            model = QtGui.QStandardItemModel()

            for i in range(5):
                model.appendRow(QtGui.QStandardItem('{} {}'.format(label, i)))

            list_view = QtWidgets.QListView()
            list_view.setModel(model)
            vbox.addWidget(list_view)


def show():
    mayaMainWindow = wrapInstance(long(omui.MQtUtil.mainWindow()), QtWidgets.QWidget)     
    win = TabWidget(parent=mayaMainWindow)
    win.show()
    return win


Marcus Ottosson

unread,
Oct 9, 2016, 9:06:28 AM10/9/16
to python_in...@googlegroups.com

I got curious about this, had a peek at the docs and found this.

The view does not take ownership of the model unless it is the model’s parent object because the model may be shared between many different views.

In your case, the model remains parent-less, which means it does not automatically get cleaned up. Having said that, it’s possible, even likely, that Python’s garbage collection takes care of it, since it will no longer be referenced anywhere.

You can use the Python module gc to find out.

Also from the docs, it says..

If both the old model and the old selection model do not have parents, or if their parents are long-lived objects, it may be preferable to call their deleteLater() functions to explicitly delete them.

So if you’d rather not find out explicitly, deleting it yourself isn’t a terrible idea.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/c75a5e80-6f62-4b91-b38b-d8b1dd8c8c0a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

johan Borgström

unread,
Oct 9, 2016, 12:32:06 PM10/9/16
to Python Programming for Autodesk Maya
Hi Marcus,

Thanks for your feedback. I decided to create a separate class for the widget that are used in the tab widget, and when that widget is deleted run a function to cleanup the model. Not sure if this is the "proper" way to do it. I have not yet tried the pymotw to inspect the gc, will look into that. 
BR,
Johan

import sys
from PySide2 import QtGui, QtCore, QtWidgets
from maya import OpenMayaUI as omui
from shiboken2 import wrapInstance
from functools import partial

class ListWidget(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super(ListWidget, self).__init__(parent) 

        vbox = QtWidgets.QVBoxLayout(self)

        self.model = QtGui.QStandardItemModel()

        self.list_view = QtWidgets.QListView()
        self.list_view.setModel(self.model)
        vbox.addWidget(self.list_view)

        self.destroyed.connect(partial(ListWidget._on_destroyed, self.model))

    def populate_list(self, name_list):
        for name in name_list:
            self.model.appendRow(QtGui.QStandardItem(name))

    @staticmethod
    def _on_destroyed(model):
       #print model
       model.deleteLater()

class TabWidget(QtWidgets.QWidget):
    
    def __init__(self, parent=None):
        super(TabWidget, self).__init__(parent) 

        self.setWindowFlags(QtCore.Qt.Tool)
        self.setGeometry(50, 200, 300, 300)
        self.setWindowTitle('Tabwidget')

        vbox = QtWidgets.QVBoxLayout(self)

        self.tab_widget = QtWidgets.QTabWidget()
        vbox.addWidget(self.tab_widget)

        label_list = ['A', 'B', 'C']

        # add tabs
        add_tabs_button = QtWidgets.QPushButton('Add Tabs')
        add_tabs_button.clicked.connect(partial(self.add_tabs, label_list))
        vbox.addWidget(add_tabs_button)

        # remove tabs
        remove_tabs_button = QtWidgets.QPushButton('Remove Tabs')
        remove_tabs_button.clicked.connect(self.remove_tabs)
        vbox.addWidget(remove_tabs_button)

    def remove_tabs(self):
        for i in range(self.tab_widget.count()):
            self.tab_widget.widget(i).deleteLater()

    def add_tabs(self, label_list):
        for label in label_list:
            list_widget = ListWidget()
            list_widget.populate_list([ '{} {}'.format(label, n) for n in range(5)])
            self.tab_widget.addTab(list_widget, label)

def show():
    mayaMainWindow = wrapInstance(long(omui.MQtUtil.mainWindow()), QtWidgets.QWidget)     
    win = TabWidget(parent=mayaMainWindow)
    win.show()
    return win

Marcus Ottosson

unread,
Oct 9, 2016, 1:45:09 PM10/9/16
to python_in...@googlegroups.com
Out of curiosity, how come you can't parent your model to your widget, and let Qt handle memory management?​

johan Borgström

unread,
Oct 9, 2016, 2:05:45 PM10/9/16
to Python Programming for Autodesk Maya
Good question :)
That is probably the easiest thing to do, thanks!
Reply all
Reply to author
Forward
0 new messages