Più finestre in PyQt4
-
22-07-2019 - |
Domanda
Ho un programma PyQt usato per visualizzare alcuni oggetti Python. Vorrei visualizzare più oggetti, ognuno nella propria finestra.
Qual è il modo migliore per realizzare applicazioni multi-finestra in PyQt4?
Attualmente ho il seguente:
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_()
Tuttavia, questo approccio non è soddisfacente, poiché sto affrontando problemi quando provo a scomporre la parte MultipleWindows nella sua stessa classe. Ad esempio:
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_()
Il codice sopra richiamerà l'inizializzatore della classe MainWindow, piuttosto che quello della sottoclasse appropriata, e genererà quindi un'eccezione.
Come posso chiamare l'inizializzatore della sottoclasse? C'è un modo più elegante per farlo?
Soluzione
Perché non usare le finestre di dialogo? In Qt non è necessario utilizzare la finestra principale se non si desidera utilizzare dock, ecc. L'uso delle finestre di dialogo avrà lo stesso effetto.
Posso anche vedere un problema nella tua logica riguardo al fatto che vuoi che la tua super classe chiami il costruttore dei suoi figli, che ovviamente può essere di qualsiasi tipo. Ti consiglio di riscriverlo come segue:
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_()
Non è una buona idea aspettarsi che la superclasse conosca il parametro da usare nella init delle sue sottoclassi poiché è davvero difficile garantire che tutto il costruttore sia lo stesso (forse l'animale dialog / window accetta i parametri diff).
Spero che sia d'aiuto.
Altri suggerimenti
Per fare riferimento alla sottoclasse che eredita la superclasse dall'interno della superclasse, sto usando self .__ class __ ()
, quindi la classe MultiWindows ora recita:
class MultiWindows(QtGui.QMainWindow):
windowList = []
def __init__(self, param):
raise NotImplementedError()
def addwindow(self, param)
win = self.__class__(param)
windowList.append(win)