简体   繁体   中英

Multiple Windows in PyQt4

I have a PyQt program used to visualize some python objects. I would like to do display multiple objects, each in its own window.

What is the best way to achieve multi-window applications in PyQt4?

Currently I have the following:

from PyQt4 import QtGui

class MainWindow(QtGui.QMainWindow):
    windowList = []

    def __init__(self, animal):
        pass

    def addwindow(self, animal)
        win = MainWindow(animal)
        windowList.append(win)

if __name__=="__main__":
    import sys

    app = QtGui.QApplication(sys.argv)

    win = QMainWindow(dog)
    win.addWindow(fish)
    win.addWindow(cat)

    app.exec_()

However, this approach is not satisfactory, as I am facing problems when I try to factor out the MultipleWindows part in its own class. For example:

class MultiWindows(QtGui.QMainWindow):
    windowList = []

    def __init__(self, param):
        raise NotImplementedError()

    def addwindow(self, param)
        win = MainWindow(param) # How to call the initializer of the subclass from here?
        windowList.append(win)

class PlanetApp(MultiWindows):
    def __init__(self, planet):
        pass

class AnimalApp(MultiWindows):
    def __init__(self, planet):
        pass

if __name__=="__main__":
    import sys

    app = QtGui.QApplication(sys.argv)

    win = PlanetApp(mercury)
    win.addWindow(venus)
    win.addWindow(jupiter)

    app.exec_()

The above code will call the initializer of the MainWindow class, rather than that of the appropriate subclass, and will thus throw an exception.

How can I call the initializer of the subclass? Is there a more elegant way to do this?

Why not using dialogs? In Qt you do not need to use the main window unless you want to use docks etc.. Using dialogs will have the same effect.

I can also see a problem in your logic regarding the fact that you want your super class to be calling the constructor of its children, which of course can be any type. I recommend you rewrite it like the following:

 class MultiWindows(QtGui.QMainWindow): def __init__(self, param): self.__windows = [] def addwindow(self, window): self.__windows.append(window) def show(): for current_child_window in self.__windows: current_child_window.exec_() # probably show will do the same trick class PlanetApp(QtGui.QDialog): def __init__(self, parent, planet): QtGui.QDialog.__init__(self, parent) # do cool stuff here class AnimalApp(QtGui.QDialog): def __init__(self, parent, animal): QtGui.QDialog.__init__(self, parent) # do cool stuff here if __name__=="__main__": import sys # really need this here?? app = QtGui.QApplication(sys.argv) jupiter = PlanetApp(None, "jupiter") venus = PlanetApp(None, "venus") windows = MultiWindows() windows.addWindow(jupiter) windows.addWindow(venus) windows.show() app.exec_() 

It is not a nice idea to expect the super class to know the parameter to be used in the init of its subclasses since it is really hard to ensure that all the constructor will be the same (maybe the animal dialog/window takes diff parameters).

Hope it helps.

In order to reference the subclass that is inheriting the super-class from inside the super-class, I am using self.__class__() , so the MultiWindows class now reads:

class MultiWindows(QtGui.QMainWindow):
windowList = []

def __init__(self, param):
    raise NotImplementedError()

def addwindow(self, param)
    win = self.__class__(param)
    windowList.append(win)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM