Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QStatusBar Deleted in Chapter 5 #1

Closed
rwilliams23 opened this issue Aug 18, 2014 · 7 comments

Comments

Projects
None yet
3 participants
@rwilliams23
Copy link

commented Aug 18, 2014

Hi!
I'm running Maya 2015 with Windows 7 64-bit. On page 163 when we open the GUI using a Shelf button, the GUI status bar does not work, (it works when called from outside Maya). This RuntimeError appears:

File "D:\MEL and Python Scripts\Python Scripts\hierarchyconvertergui.py", line 32, in update_statusbar
controller.selectionChanged.connect(update_statusbar)
RuntimeError: Internal C++ object (PySide.QtGui.QStatusBar) already deleted.

In an e-mail, you explained this was what was happening:

That issue is due to Maya cleaning up the memory underlying the Qt object before Python is actually done with it. In other words, PySide (the Qt bindings) have a reference to some C++ Qt object, but somehow it has decided that C++ object can be deleted. But Python still has a reference to the PySide object, and when Python accesses it: BAM!

And suggested this workaround:

my_hacky_list = []
def some_func():
    my_statusbar = # create status bar
    my_hacky_list.append(my_statusbar)
    def update_statusbar():
        # ... do some stuff with my_statusbar ....
    controller.selectionChanged.connect(update_statusbar)

I'm just starting to cut my teeth on this stuff and tried the following, but the problem continued....

statusbar_list = []
def keep_statusbar():
    my_statusbar = statusbar
    statusbar_list.append(my_statusbar)
    def update_statusbar(newsel):
        if not newsel:
            txt = 'Nothing selected.'
        elif len(newsel) == 1:
            txt = '%s selected.' % newsel[0]
        else:
            txt = '%s objects selected.' % len(newsel)
        my_statusbar.showMessage(txt)
    controller.selectionChanged.connect(update_statusbar)    

Thanks!
Ric

@rgalanakis

This comment has been minimized.

Copy link
Owner

commented Aug 19, 2014

Hi @rwilliams23, try changing the code to something like this (from https://github.com/rgalanakis/practicalmayapython/blob/master/src/chapter5/hierarchyconvertergui.py#L10 ):

hacktastic_list = []  # ADD THIS LINE
def create_window(controller, parent=None):
    window = ConverterWindow(parent)
    window.setWindowTitle('Hierarchy Converter')
    statusbar = window.statusBar()
    hacktastic_list.append(statusbar)  # ADD THIS LINE

Tell me if that fixes the problem. I can't get PySide installed into a virtualenv on this machine, but I'll test this out on OSX soon and fix it from a Windows box when I can (may be a few weeks).

@rwilliams23

This comment has been minimized.

Copy link
Author

commented Aug 20, 2014

Hi Rob,
No joy... same error message and no statusbar. In case it's something stupid I've done, below is all of hierarchyconverterui.py with your suggested change. As it is, no worries--and certainly no rush. I'm at the stage where I simply want to read code and see if I can understand it. I'm thrilled about your book; it's exactly what I've been looking for.
All the best to you!
Ric

from qtshim import QtGui, QtCore, Signal

class HierarchyConverterController(QtCore.QObject):
    selectionChanged = Signal(list)

class ConverterWindow(QtGui.QMainWindow):
    convertClicked = Signal(str)

hacktastic_list = []

def create_window(controller, parent=None):
    window = ConverterWindow(parent)  #This is indented in the code, but not here in this note.
    window.setWindowTitle('Hierarchy Converter') #This is indented in the code.
    statusbar = window.statusBar() #This is indented in the code.
    hacktastic_list.append(statusbar) #This is indented in the code.

    container = QtGui.QWidget(window)
    label = QtGui.QLabel('Prefix:', container)
    textbox = QtGui.QLineEdit(container)
    button = QtGui.QPushButton('Convert', container)

    def onclick():
        window.convertClicked.emit(textbox.text())
    button.clicked.connect(onclick)

    def update_statusbar(newsel):
        if not newsel:
            txt = 'Nothing selected'
        elif len(newsel) == 1:
            txt = '%s selected.' % newsel[0]

        else:
            txt = '%s objects selected.' % len(newsel)
        statusbar.showMessage(txt)
    controller.selectionChanged.connect(update_statusbar)

    layout = QtGui.QHBoxLayout(container)
    container.setLayout(layout)
    # Add them to the layout, first widget added is left most
    layout.addWidget(label)
    layout.addWidget(textbox)
    layout.addWidget(button)
    window.setCentralWidget(container)

    return window
def _pytest():
    import random

    controller = HierarchyConverterController()
    def nextsel():
        return random.choice([
                              [],
                              ['single'],
                              ['single', 'double']])



    def onconvert(prefix):
        print 'Convert clicked! Prefix:', prefix
        controller.selectionChanged.emit(nextsel())

    app = QtGui.QApplication([])
    win = create_window(controller)
    win.convertClicked.connect(onconvert)
    win.show()
    app.exec_()

if __name__ == '__main__':
    _pytest()
@ragingViking

This comment has been minimized.

Copy link
Contributor

commented Oct 15, 2014

In create_window(), change statusbar = window.statusBar() to statusbar = QtGui.QStatusBar()
and at the bottom of the function, add the line window.setStatusBar(statusbar)

def create_window(controller, parent=None):
    window = ConverterWindow(parent)
    window.setWindowTitle('Hierarchy Converter')

    container = QtGui.QWidget(window)
    label = QtGui.QLabel('Prefix:', container)
    textbox = QtGui.QLineEdit(container)
    button = QtGui.QPushButton('Convert', container)
    # change this line
    statusbar = QtGui.QStatusBar()

    def onclick():
        window.convertClicked.emit(textbox.text())
    button.clicked.connect(onclick)

    def update_statusbar(newsel):
        if not newsel:
            txt = 'Nothing selected.'
        elif len(newsel) == 1:
            txt = '%s selected.' % newsel[0]
        else:
            txt = '%s objects selected' % len(newsel)
        statusbar.showMessage(txt)
    controller.selectionChanged.connect(update_statusbar)

    layout = QtGui.QHBoxLayout(container)
    container.setLayout(layout)
    layout.addWidget(label)
    layout.addWidget(textbox)
    layout.addWidget(button)
    window.setCentralWidget(container)
    # add this line
    window.setStatusBar(statusbar)

    return window
@rgalanakis

This comment has been minimized.

Copy link
Owner

commented Oct 15, 2014

Thanks @ragingViking , will ask some folks to test this out.

@rgalanakis

This comment has been minimized.

Copy link
Owner

commented Oct 15, 2014

@ragingViking , I have reports this worked. Can you create a Pull Request so you get proper credit for the fix? :) Otherwise I can do it myself.
Thanks again!

@ragingViking

This comment has been minimized.

Copy link
Contributor

commented Oct 16, 2014

No problem. I'm just excited it worked :)

@rgalanakis

This comment has been minimized.

Copy link
Owner

commented Oct 16, 2014

Fixed in #2

@rgalanakis rgalanakis closed this Oct 16, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.