My question is tough to explain but I am trying my best. Please help me in this regard.
I designed a gui in QtDesigner and converted .ui files into .py e.g. main_window.py. Now in order to avoid changing in main_window.py I created another class for listeners.
class Main():
window = None
app = None
def __init__(self):
self.launch()
self.attach_listener()
self.execute()
''' Launch GUI '''
def launch(self):
self.app = QtGui.QApplication(sys.argv)
self.window = Ui_MainWindow()
self.window.show()
''' Execute Window '''
def execute(self):
sys.exit(self.app.exec_())
''' Attach Listeners '''
def attach_listener(self):
self.window.add_button.clicked.connect(self.add_listener)
self.window.delete_button.clicked.connect(self.delete_listener)
self.window.update_button.clicked.connect(self.update_listener)
self.window.connect(self.window.combo_box, QtCore.SIGNAL('activated(QString)'), self.logout_listener)
I have another child_window.py with same structure, but I can't open that window from this one because of QApplication. I searched for the answer but couldn't apply on my code. Those answers were applicable when class was extending from QtGui.QMainWindow or QtGui.QWidget, but my scenario is different.
Best Answer
You are mixing up the Ui_MainWindow object with the actual window object (QMainWindow, QDialog,QWidget etc.) self.window = Ui_MainWindow() doesn't do anything because the class you are attaching it to is not a Window. You need to create a window and apply the Ui_MainWindow to it.
Apparently you can make this work, but it doesn't look pretty. You need to access your widgets via findChild. The only benefit I can see is that you don't run pyside-uic after changing a form in the designer, and that's pretty easy.
The easier way
When you use pyuic / pyside-uic it converts the .ui files to .py files. You shouldn't edit the .py's as they will be overwritten the next time you use QtDesigner. You need to create a window class and apply the UI class to it.
Setting up a new form
Some of these module names might seem a bit awkward, but I've settled on them because in the past I've had trouble with name clashes between modules and classes; caused by me not understanding how Qt Designer was going to handle it's naming.
If you look at the file that pyside-uic created, the top of it contains the correct class and method names that you need to use in your mainWinClass.py
mainWinui.py
Create a new mainwinClass.py and copy the correct imports and class names to it, plus a bit of boilerplate to load the .ui.
It looks like this:
mainWinClass.py
Then use another file to launch the app itself, and to maintain some non GUI aspects of the app, like updaters or global logging. I've seen code where all the child windows are instantiated in here to, but I don't (normally) do it that way. I keep them in the main form instead. It depends on how you intend to design the app.
appname.py
Now for any child windows follow the same again.
Modal forms
In Qt Designer create a new 'Dialog with buttons bottom'. Add widgets as desired and save as dialogAddStaffui.ui.
Run
Create a new, empty text document called dialogAddStaffClass.py and using dialogAddStaffui.ui as a reference for class names etc. edit dialogAddStaffClass.py to look like this:
dialogAddStaffClass
Those two imports are the only ones needed here. If you are trying to copy this, realise that in the Qt Designer I have
windowModality = ApplicationModal and the form was a "Dialog with Buttons Bottom"
For these simple forms, they have an accept method that checks the validity of data that the user has entered and closes with self.done(1). If you want to see how the validation and close is handled:
dialogAddStaffClass
With these dialog forms Qt has automatically set the OK button to fire accept. I just overrode that method.
If you want communication between parent and child you can either set a property on the child that references the parent, or read the the properties of the child after it closes, but before it's variable gets garbage collected. There can be issues with creating circular references so be careful.
As the new form is modal, the user can't interact with the Main Form until they have closed the Child Form, and the function that launches the chil d window will halt until the child window is closed, therefore it's ok to use a local variable to hold the child class.
The 'Add Staff' button is connected to the addStaffMember function.
mainWinClass.py
Because the child form is run with exec_, the main form waits untill the child form closes before continuing. When the function exits the addStaffForm variable is garbage collected, so there is no longer any reference to the attributes of the child form. (and probably no form ...)
If you want to open a Long lived form, you would instantiate it somewhere more long lasting.
Non Modal forms
Here is an example of a SisterForm. It is was created in the designer from the 'Main Window' type (It has it's own menu's and Status bar etc.). If you don't need these frills, use a Dialog form but set it's windowModality to NonModal.
sisterWinui.ui
Run uic
Create a file sisterwinClass.py - set up it's import and init
sisterwinClass.py
In Qt Designer, add a button or whatever to your main form to launch sisterForm. Then make some edits to the mainwinClass. Make a variable to hold it in a long lived place
mainwinClass
I hope that covers what you were looking for now ? If are trying to find out how to hide the main window , look here Happy hacking :-)