2011-12-17 11 views
5

Durante intervalli regolari del mio programma, è necessario aggiungere un blocco (di 3 riquadri) a un layout orizzontale. Poiché i widget all'interno di ciascun blocco sono importanti l'uno con l'altro, desidero incapsulare ogni pila come se fosse un proprio widget (rendendo il layout molto più semplice per l'attività).PyQt4 - Struttura della classe del widget personalizzata?

Sto riscontrando problemi nel far riconoscere a PyQt4 il mio "stack" come widget.

Ho creato lo stack di widget in Qt Designer (come forma: widget) e lo ho convertito in un file .py tramite
'pyuic4 DesignerFile.ui> ClassFile.py'.

Ora non riesco a aggiungere questo "stack" (widget padre di 3 widget figlio) al layout tramite .addWidget (Classe).

ho provato la costruzione di una super classe della classe di stack (perché ho bisogno di aggiungere ulteriori funzionalità alla pila), ma l'istanza della classe è o ...

  • Non riconosciuta come un widget
  • Invisibile
  • difettoso perché non ho idea di come strutturare la super classe.

Ecco quello che sto in mancanza con al momento (anche se si tratta di struttura di classe 8 Ho provato):

from ClassFile import ClassCode 

class Stack(ClassCode): 
    def __init__(self,parent= None): 
     QtGui.QWidget.__init__(self,parent) 

Qualcuno potrebbe aiutarmi a strutturare questo o mi portano ad alcuni buoni esempi ?
(ho imitato il codice in entrambe le seguenti fonti, ma senza alcun risultato !!
http://lateral.netmanagers.com.ar/stories/27.html#what-you-need-to-follow-the-tutorial
http://zetcode.com/tutorials/pyqt4/customwidgets/)

Grazie!

Spec:
pitone 2.7.2
PyQt4
Windows 7

risposta

5

Quando si compila un modulo python da un file ui con le opzioni di default, sarà (tra le altre cose) di generare un semplice "messa a punto" di classe. Di base, la classe di installazione sarà simile a questa:

class Ui_ClassCode(object): 
    def setupUi(self, ClassCode): 
     ClassCode.setObjectName("ClassCode") 
     # bunch of boiler-plate ui code goes here 
     self.retranslateUi(ClassCode) 
     QtCore.QMetaObject.connectSlotsByName(ClassCode) 

    def retranslateUi(self, ClassCode): 
     pass 

Ci sono un paio di problemi da notare qui che sono rilevanti per la domanda.

In primo luogo, la classe di installazione è progettata per essere utilizzata come mixin anziché come sottoclasse diretta.Il suo compito è "iniettare" ui in un widget host passato al metodo setupUI.

In secondo luogo, alla classe di installazione viene assegnato un identificatore brutto, unpitonico che viene creato anteponendo "Ui_" alla proprietà objectName impostata in Designer.

Fortunatamente, pyuic4 offre un modo per aggirare questi due problemi. Tutto ciò che è richiesto è di utilizzare l'opzione -w durante la compilazione del modulo python dal file ui:

pyuic4 -w designerfile.ui > classfile.py 

Questo aggiungerà una classe wrapper che (1) può essere facilmente sottoclassi, e (2) ha il nome della classe che maledettamente gli hai dato in Qt Designer.

La classe wrapper sarà simile a questo:

class ClassCode(QtGui.QWidget, Ui_ClassCode): 
    def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()): 
     QtGui.QWidget.__init__(self, parent, f) 

     self.setupUi(self) 

Come si può vedere, non fa nulla di speciale: si potrebbe facilmente replicare ciò che fa nel proprio codice. Ma, IMO, rende i moduli compilati molto più intuitivi da usare.

Ad esempio:

from PyQt4 import QtGui, QtCore 
from classfile import ClassCode 

class Stack(ClassCode): 
    def __init__(self, parent=None): 
     ClassCode.__init__(self, parent) 

class Window(QtGui.QMainWindow): 
    def __init__(self): 
     QtGui.QMainWindow.__init__(self) 
     self.stack = Stack(self) 
     self.setCentralWidget(self.stack) 
+0

È possibile essere in grado di passare una stringa al costruttore (quando l'istanziazione del widget) deve essere utilizzata tramite il widget? Es: x = Stack ('cat') –

+1

@AntiEarth. Certo: puoi progettare la sottoclasse 'Stack' nel modo che preferisci - proprio come sottoclasse qualsiasi altro widget Qt. Quindi la firma di 'Stack .__ init__' potrebbe essere modificata ad es. '__init __ (self, name, parent = None)'. – ekhumoro

1

In primo luogo, è più appropriato chiamare il genitore __init__ con l'uso di super. Ciò assicurerà che il metodo nella super classe corretta venga invocato. In secondo luogo, quando si utilizza una classe costruita con pyuic, è necessario chiamare self.setupUi(self) dal metodo __init__. Infine, devi assicurarti che siano ereditate multiple sia dalla classe Qt appropriata sia dalla classe generata da pyuic (che è davvero più di un mixin).

Quindi, qualcosa di simile:

from ClassFile import ClassCode 

class Stack(QtGui.QWidget, ClassCode): 
    def __init__(self,parent= None): 
     super(Stack, self).__init__(parent) 
     self.setupUi(self) 
+1

Egli in realtà dovrebbe essere ereditato dal primo QWidget desiderato, e in secondo luogo dalla classCode che è stato generato da pyuic – jdi

+0

Grazie per la cattura di questo. Ho aggiornato la mia risposta. –