Diferència entre revisions de la pàgina «PyQt: pintar dintre d'un widget»

De Cacauet Wiki
Salta a la navegació Salta a la cerca
(super del constructor erroni)
 
(Hi ha 5 revisions intermèdies del mateix usuari que no es mostren)
Línia 3: Línia 3:
 
* Creem la nostra '''classe derivant-la de QWidget''' (en el nostre exemple la classe Pantalla)
 
* Creem la nostra '''classe derivant-la de QWidget''' (en el nostre exemple la classe Pantalla)
 
* Reimplementem el mètode paintEvent que es crida automàticament quan es repinta el Widget.
 
* Reimplementem el mètode paintEvent que es crida automàticament quan es repinta el Widget.
* Dintre de paintEvent(self,e) podem pintar el què vulguem mitjançant el QPainter
+
* Dintre de paintEvent(self,e) podem pintar el què vulguem mitjançant l'[http://doc.qt.digia.com/qt/qpainter.html objecte QPainter].
 +
* L'[http://doc.qt.digia.com/qt/qpainter.htmlhttp://doc.qt.digia.com/qt/qpainter.html objecte QPainter] ve a ser un "llapis" per dibuixar en el Widget. Feu un cop d'ull a la documentació, veureu que a part de la funció ''drawEllipse'' que fem servir, n'hi ha un fotimer com ''drawRect'', ''drawArc'', ''drawPixmap'', etc.
  
=== Classe derivada ===
+
 
 +
== Classe derivada ==
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 
class Pantalla(QtGui.QWidget):
 
class Pantalla(QtGui.QWidget):
Línia 11: Línia 13:
 
         # ULL: cridar el constructor de la classe base és IMPRESCINDIBLE
 
         # ULL: cridar el constructor de la classe base és IMPRESCINDIBLE
 
         # (si sobreescrivim el constructor __init__, si no, no cal)
 
         # (si sobreescrivim el constructor __init__, si no, no cal)
         super(QtGui.QWidget,self).__init__()
+
         super(Pantalla,self).__init__()
 
         self.initUI()
 
         self.initUI()
 
      
 
      
Línia 43: Línia 45:
 
<br>
 
<br>
  
=== Exercici: control d'una pilota ===
+
== Exercici: control d'una pilota ==
 
L'objectiu és pintar una pilota i controlar-la amb els sliders (posició vertical i horitzontal).
 
L'objectiu és pintar una pilota i controlar-la amb els sliders (posició vertical i horitzontal).
  
Línia 50: Línia 52:
 
# Canviem el textedit per una classe nova nostra (Pantalla) heretada de QWidget (detallada més amunt)
 
# Canviem el textedit per una classe nova nostra (Pantalla) heretada de QWidget (detallada més amunt)
 
# Afegim paintEvent i el disparem (de moment un print) només al repintar la pantalla (canvi de task)
 
# Afegim paintEvent i el disparem (de moment un print) només al repintar la pantalla (canvi de task)
# Pintem al widget Pantalla() amb QPainter (qualsevol cosa).
+
# Pintem al widget Pantalla() amb [http://doc.qt.digia.com/qt/qpainter.html QPainter].
# Posem posx, posy i pintem una pilota (o el què volguem)
+
#: Comença per la pilota amb un ''drawEllipse'' com el de l'exemple però també prova ''drawRect'', ''drawArc'' o altres opcions del QPainter (caldrà que miris la documentació).
# Connectem els sliders amb posx i posy directament (val i pos).
+
# Per poder seguir ens convé tenir els valors ''posx'' i ''posy'' com a atributs de l'objecte ''Pantalla'' (i no com a variables locals). Crea, doncs, aquests atributs en ''Pantalla'' i pinta la pilota amb aquests valors interns. Després modificarem aquests valors amb els sliders.
#: IMPORTANT: quan canvieu el valor de posx o posy cal repintar la pantalla (no es fa automàticament). Utilitzeu la funció '''''repaint()''''' del widget per forçar una repintada.
+
# Connectem els sliders amb funcions que modifiquin la ''posx'' i la ''posy''. De moment assigna'ls el valor que t'arriba del slider i prou.
 +
#* [[PyQt: connectant signals amb slots]]
 +
#* IMPORTANT: quan canvieu el valor de posx o posy cal repintar la pantalla (no es fa automàticament). Utilitzeu la funció '''''repaint()''''' del widget per forçar una repintada.
 
#: [[Fitxer:Qt-piloteta1.png]]
 
#: [[Fitxer:Qt-piloteta1.png]]
# Calculem la posx i posy d'acord amb els límits dels sliders i de la geometria de la pantalla. Es tracta d'una senzilla regla de 3:<pre>x = valor_slider * amplada / total_ticks_slider</pre>
+
# Calculem la posx i posy d'acord amb els límits dels sliders i de la geometria de la pantalla (que pot variar, per exemple, al maximitzar-la). Es tracta d'una senzilla regla de 3:<pre>x = valor_slider * amplada / total_ticks_slider</pre>
 
#: 100 és el total de ticks del ''slider'', i l'amplada la podeu esbrinar del propi widget amb width()
 
#: 100 és el total de ticks del ''slider'', i l'amplada la podeu esbrinar del propi widget amb width()
 
# Per canviar el color del background teniu [http://stackoverflow.com/questions/177778/in-qt-how-do-i-set-the-background-color-of-a-widget-like-combobox-or-double-spi aquest link]. A mi m'ha funcionat el del QPalette i no el de QStyleSheet.
 
# Per canviar el color del background teniu [http://stackoverflow.com/questions/177778/in-qt-how-do-i-set-the-background-color-of-a-widget-like-combobox-or-double-spi aquest link]. A mi m'ha funcionat el del QPalette i no el de QStyleSheet.
 +
# [[PyQt: Events de teclat]]: opcionalment pots afegir control del teclat als sliders.
 
<br>
 
<br>
  

Revisió de 15:56, 1 març 2013

Pintar en els widgets[modifica]

Anem a pintar els nostres propis widgets en Qt. Per fer això es fa de la següent manera:

  • Creem la nostra classe derivant-la de QWidget (en el nostre exemple la classe Pantalla)
  • Reimplementem el mètode paintEvent que es crida automàticament quan es repinta el Widget.
  • Dintre de paintEvent(self,e) podem pintar el què vulguem mitjançant l'objecte QPainter.
  • L'objecte QPainter ve a ser un "llapis" per dibuixar en el Widget. Feu un cop d'ull a la documentació, veureu que a part de la funció drawEllipse que fem servir, n'hi ha un fotimer com drawRect, drawArc, drawPixmap, etc.


Classe derivada[modifica]

class Pantalla(QtGui.QWidget):
    def __init__(self):
        # ULL: cridar el constructor de la classe base és IMPRESCINDIBLE
        # (si sobreescrivim el constructor __init__, si no, no cal)
        super(Pantalla,self).__init__()
        self.initUI()
    
    def initUI(self):
        # inicialitzem aqui si tenim objectes interns
        pass

    # la funció paintEvent es crida cada cop que es pinta la pantalla
    # no cal cap connect(), ja ve connectada per la QApplication
    def paintEvent(self,e):
        # podriem liar-nos a pintar aquí mateix, o examinar l'event "e"
        # anem al lio... necessitem un objecte QPainter
        qp = QtGui.QPainter()
        qp.begin( self )
        self.pintaPilota( qp )
        qp.end()
        
    def pintaPilota(self, qp):
        # podem optar per un Pen (pinta perifèric)
        color = QtGui.QColor( 0, 0, 0 )
        color.setNamedColor( '#d4d4d4' )
        qp.setPen( color )
        # o bé per un Brush (farcit). El color és RGB, òbviament
        qp.setBrush( QtGui.QColor(200, 0, 0) )

        # PER FI, PINTEM LA PILOTA!
        posx, posy = 20, 20
        radx, rady = 10, 10
        qp.drawEllipse( posx, posy , radx, rady )


Exercici: control d'una pilota[modifica]

L'objectiu és pintar una pilota i controlar-la amb els sliders (posició vertical i horitzontal).

  1. Feu l'anterior exercici dels sliders (en la intro de PyQt).
    Qt-sliders1.png
  2. Canviem el textedit per una classe nova nostra (Pantalla) heretada de QWidget (detallada més amunt)
  3. Afegim paintEvent i el disparem (de moment un print) només al repintar la pantalla (canvi de task)
  4. Pintem al widget Pantalla() amb QPainter.
    Comença per la pilota amb un drawEllipse com el de l'exemple però també prova drawRect, drawArc o altres opcions del QPainter (caldrà que miris la documentació).
  5. Per poder seguir ens convé tenir els valors posx i posy com a atributs de l'objecte Pantalla (i no com a variables locals). Crea, doncs, aquests atributs en Pantalla i pinta la pilota amb aquests valors interns. Després modificarem aquests valors amb els sliders.
  6. Connectem els sliders amb funcions que modifiquin la posx i la posy. De moment assigna'ls el valor que t'arriba del slider i prou.
    • PyQt: connectant signals amb slots
    • IMPORTANT: quan canvieu el valor de posx o posy cal repintar la pantalla (no es fa automàticament). Utilitzeu la funció repaint() del widget per forçar una repintada.
    Qt-piloteta1.png
  7. Calculem la posx i posy d'acord amb els límits dels sliders i de la geometria de la pantalla (que pot variar, per exemple, al maximitzar-la). Es tracta d'una senzilla regla de 3:
    x = valor_slider * amplada / total_ticks_slider
    100 és el total de ticks del slider, i l'amplada la podeu esbrinar del propi widget amb width()
  8. Per canviar el color del background teniu aquest link. A mi m'ha funcionat el del QPalette i no el de QStyleSheet.
  9. PyQt: Events de teclat: opcionalment pots afegir control del teclat als sliders.


Timers i pilotetes[modifica]

Ens proposem l'objectiu de fer un widget on aparegui una pilota que rebota a les seves parets.

Seguiu el següent article: PyQt: Timers i pilotes rebotant