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?
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.
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
class StartQT4(QtGui.QMainWindow): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent)
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:
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)).