views:

443

answers:

3

I'm trying to use pyqt to show a custom QDialog window when a button on a QMainWindow is clicked. I keep getting the following error:

$ python main.py 
DEBUG: Launch edit window
Traceback (most recent call last):
  File "/home/james/Dropbox/Database/qt/ui_med.py", line 23, in launchEditWindow
    dialog = Ui_Dialog(c)
  File "/home/james/Dropbox/Database/qt/ui_edit.py", line 15, in __init__
    QtGui.QDialog.__init__(self)
TypeError: descriptor '__init__' requires a 'sip.simplewrapper' object but received a 'Ui_Dialog'

I've gone over several online tutorials, but most of them stop just short of showing how to use a non built-in dialog window. I generated the code for both the main window and the dialog using pyuic4. What I think should be the relevant code is below. What am I missing here?

class Ui_Dialog(object):
    def __init__(self, dbConnection):
     QtGui.QDialog.__init__(self)
     global c
     c = dbConnection

class Ui_MainWindow(object):
    def __init__(self, dbConnection):
     global c
     c = dbConnection

    def launchEditWindow(self):
     print "DEBUG: Launch edit window"
     dialog = QtGui.QDialog()
     dialogui = Ui_Dialog(c)
     dialogui = setupUi(dialog)
     dialogui.show()

class StartQT4(QtGui.QMainWindow):
    def __init__(self, parent=None):
     QtGui.QWidget.__init__(self, parent)
     conn = sqlite3.connect('meds.sqlite')
     c = conn.cursor()
     self.ui = Ui_MainWindow(c)
     self.ui.setupUi(self)

def main():
    app = QtGui.QApplication(sys.argv)
    program = StartQT4()
    program.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Bonus question: since it looks like you can't pass arguments in pyqt function callbacks, is setting something which would otherwise be passed as an argument (the poorly named "c") to be global the best way to get information into those functions?

A: 
class StartQT4(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

Why QtGui.QWidget.__init___ ??? Use insted:

class StartQT4(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)

You must call __init__ methon from base class (name in parenthesis '()')

QDialog have two useful routins:

exec_()
show()

First wait for closing dialog and then you can access any field form dialog. Second show dialog but don't wait, so to work properly you must set some slot/signals connections to respond for dialog actions.

eg. for exec_():

class Dialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(parent)
        line_edit = QLineEdit()
    ...

dialog = Dialog()
if dialog.exec_():   # here dialog will be shown and main script will wait for its closing (with no errors)
    data = dialog.line_edit.text()

Small tip: can you change your ui classes into widgets (with layouts). And perhaps problem is that your __init__ should be __init__(self, parent=None, dbConnection)

Because when you create new widget in existing one PyQt may try to set it as children of existing one. (So change all init to have additional parent param (must be on second position)).

przemo_li
Ok. But my program still functions the same as before. Any idea why I'm getting the error "descriptor '__init__' requires a 'sip.simplewrapper' object but received a 'Ui_Dialog'" when I try to open a second window?
James
Ok edited. Now look at small tip.
przemo_li
A: 

Ui_Dialog should inherent from QtGui.QDialog, not object.

class Ui_Dialog(QtGui.QDialog):
    def __init__(self, dbConnection):
        QtGui.QDialog.__init__(self)
        global c
        c = dbConnection
Gary van der Merwe
A: 

I've done like this in the past, and i can tell it works. assuming your button is called "Button"

class Main(QtGui.QMainWindow):
    ''' some stuff '''
    def on_Button_clicked(self, checked=None):
        if checked==None: return
        dialog = QDialog()
        dialog.ui = Ui_MyDialog()
        dialog.ui.setupUi(dialog)
        dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        dialog.exec_()

This works for my application, and I believe it should work with yours as well. hope it'll help, it should be pretty straight forward to do the few changes needed to apply it to your case. have a good day everybody.

japs