How to create new PyQt4 windows from an existing window?
Asked Answered
A

2

7

I've been trying to call a new window from an existing one using python3 and Qt4.

I've created two windows using Qt Designer (the main application and another one), and I've converted the .ui files generated by Qt Designer into .py scripts - but I can't seem to create new windows from the main application.

I tried doing this:

############### MAIN APPLICATION SCRIPT ################

from PyQt4 import QtCore, QtGui
import v2

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(194, 101)
        self.button1 = QtGui.QPushButton(Form)
        self.button1.setGeometry(QtCore.QRect(50, 30, 99, 23))
        self.button1.setObjectName(_fromUtf8("button1"))

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
        self.button1.setText(QtGui.QApplication.translate("Form", "Ventana", None, QtGui.QApplication.UnicodeUTF8))

        self.button1.connect(self.button1, QtCore.SIGNAL(_fromUtf8("clicked()")), self.mbutton1)

    def mbutton1(self):
        v2.main()



if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Form = QtGui.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())
################## SECOND WINDOW #######################

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(400, 300)
        self.label = QtGui.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(160, 40, 57, 14))
        self.label.setObjectName(_fromUtf8("label"))

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
        self.label.setText(QtGui.QApplication.translate("Form", "LABEL 2", None, QtGui.QApplication.UnicodeUTF8))

def main():
    import sys
    app = QtGui.QApplication(sys.argv)
    Form = QtGui.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

But I get this Error message:

 QCoreApplication::exec: The event loop is already running
 QPixmap: Must construct a QApplication before a QPaintDevice
Arce answered 22/11, 2012 at 17:28 Comment(0)
C
13

Although pyuic can create executable scripts with the -x, --execute option, it is mainly intended for testing.

The main purpose of pyuic is to create static python modules from Qt Desgner ui files that allow you to import the contained GUI classes into your application.

Let's say you've created two ui files using Qt Designer and named them v1.ui and v2.ui.

You would then create the two python modules like this:

pyuic4 -o v1.py v1.ui
pyuic4 -o v2.py v2.ui

Next, you would write a separate main.py script that imports the GUI classes from the modules, and creates instances of them as needed.

So your main.py could look something like this:

from PyQt4 import QtGui
from v1 import Ui_Form1
from v2 import Ui_Form2

class Form1(QtGui.QWidget, Ui_Form1):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setupUi(self)
        self.button1.clicked.connect(self.handleButton)
        self.window2 = None

    def handleButton(self):
        if self.window2 is None:
            self.window2 = Form2(self)
        self.window2.show()

class Form2(QtGui.QWidget, Ui_Form2):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setupUi(self)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Form1()
    window.show()
    sys.exit(app.exec_())

Note that I have changed the names of your GUI classes slightly to avoid namespace clashes. To give the GUI classes better names, just set the objectName property of the top-level class in Qt Desgner. And don't forget to re-run pyuic after you've made your changes!

Catheycathi answered 22/11, 2012 at 19:47 Comment(0)
B
5

You can only create one QApplication. After you have created it you can create how many windows you want.

For example:

from PyQt4 import QtGui, QtCore

class MyWindow(QtGui.QDialog):    # any super class is okay
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)
        self.button = QtGui.QPushButton('Press')
        layout = QtGui.QHBoxLayout()
        layout.addWidget(self.button)
        self.setLayout(layout)
        self.button.clicked.connect(self.create_child)
    def create_child(self):
        # here put the code that creates the new window and shows it.
        child = MyWindow(self)
        child.show()


if __name__ == '__main__':
    # QApplication created only here.
    app = QtGui.QApplication([])
    window = MyWindow()
    window.show()
    app.exec_()

Every time you click the button will create a new window.

You can adapt the above example to use the windows you created with the Designer.

On a side note:

Never ever edit the result of pyuic. Those files should not be changed. This means: do not add the mbutton1 method to the Ui_Form.

If you have the file mywindow_ui.py that was created by pyuic, then you create the file mywindow.py and put something like this:

from PyQt4 import QtCore, QtGui
from mywindow_ui import Ui_MyWindow

class MyWindow(QtGui.QWidget, Ui_MyWindow):   #or whatever Q*class it is
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)
        self.setupUi(self)
    def create_child(self):   #here should go your mbutton1
        # stuff
#etc.

Now from your main file main.py you do:

from PyQt4 import QtGui

from mywindow import MyWindow


# ...

if __name__ == '__main__':
    app = QtGui.QApplication([])
    window = MyWindow()
    window.show()
    app.exec_()
Borries answered 22/11, 2012 at 17:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.