Plusieurs fenêtres dans PyQt4
-
22-07-2019 - |
Question
J'ai un programme PyQt utilisé pour visualiser certains objets en python. J'aimerais afficher plusieurs objets, chacun dans sa propre fenêtre.
Quel est le meilleur moyen de réaliser des applications multi-fenêtres dans PyQt4?
Actuellement, j'ai les éléments suivants:
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_()
Cependant, cette approche n’est pas satisfaisante car je rencontre des problèmes lorsque je tente de décomposer la partie MultipleWindows dans sa propre classe. Par exemple:
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_()
Le code ci-dessus appellera l'initialiseur de la classe MainWindow, plutôt que celui de la sous-classe appropriée, et lèvera donc une exception.
Comment puis-je appeler l'initialiseur de la sous-classe? Y a-t-il un moyen plus élégant de faire cela?
La solution
Pourquoi ne pas utiliser les dialogues? Dans Qt, vous n'avez pas besoin d'utiliser la fenêtre principale sauf si vous souhaitez utiliser des docks, etc. L'utilisation de boîtes de dialogue aura le même effet.
Je peux également voir un problème dans votre logique concernant le fait que vous souhaitez que votre super-classe appelle le constructeur de ses enfants, qui peut bien entendu être de tout type. Je vous recommande de le réécrire comme suit:
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_()
Ce n’est pas une bonne idée de s’attendre à ce que la super classe connaisse le paramètre à utiliser dans init de ses sous-classes car il est vraiment difficile de s’assurer que tous les constructeurs seront identiques (peut-être que l’animal dialog / window prend les paramètres diff).
J'espère que ça aide.
Autres conseils
Pour référencer la sous-classe qui hérite de la super-classe de l'intérieur de la super-classe, j'utilise self .__ class __ ()
. La classe MultiWindows lit donc maintenant:
class MultiWindows(QtGui.QMainWindow):
windowList = []
def __init__(self, param):
raise NotImplementedError()
def addwindow(self, param)
win = self.__class__(param)
windowList.append(win)