Múltiples ventanas en PyQt4
-
22-07-2019 - |
Pregunta
Tengo un programa PyQt usado para visualizar algunos objetos de Python. Me gustaría mostrar varios objetos, cada uno en su propia ventana.
¿Cuál es la mejor manera de lograr aplicaciones de múltiples ventanas en PyQt4?
Actualmente tengo lo siguiente:
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_()
Sin embargo, este enfoque no es satisfactorio, ya que estoy enfrentando problemas cuando intento factorizar la parte MultipleWindows en su propia clase. Por ejemplo:
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_()
El código anterior llamará al inicializador de la clase MainWindow, en lugar del de la subclase apropiada, y por lo tanto arrojará una excepción.
¿Cómo puedo llamar al inicializador de la subclase? ¿Hay alguna forma más elegante de hacer esto?
Solución
¿Por qué no usar diálogos? En Qt no necesita usar la ventana principal a menos que quiera usar muelles, etc. Usar diálogos tendrá el mismo efecto.
También puedo ver un problema en su lógica con respecto al hecho de que desea que su superclase llame al constructor de sus hijos, que por supuesto puede ser de cualquier tipo. Te recomiendo que lo reescribas así:
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_()
No es una buena idea esperar que la superclase conozca el parámetro que se utilizará en el init de sus subclases, ya que es realmente difícil asegurarse de que todo el constructor sea el mismo (tal vez el animal dialog / window toma parámetros diff).
Espero que ayude.
Otros consejos
Para hacer referencia a la subclase que hereda la superclase desde dentro de la superclase, estoy usando self .__ class __ ()
, por lo que la clase MultiWindows ahora lee:
class MultiWindows(QtGui.QMainWindow):
windowList = []
def __init__(self, param):
raise NotImplementedError()
def addwindow(self, param)
win = self.__class__(param)
windowList.append(win)