Diferència entre revisions de la pàgina «PyQt: Timers i pilotes rebotant»

De Cacauet Wiki
Salta a la navegació Salta a la cerca
Línia 22: Línia 22:
 
Per poder moure la pilota necessitareu un '''Timer: un temporitzador que regularment faci una crida a una funció''', en el nostre cas per repintar la pantalla. En cada execució pintarem la pilota recalculant les seves noves coordenades i així crearem el moviment.
 
Per poder moure la pilota necessitareu un '''Timer: un temporitzador que regularment faci una crida a una funció''', en el nostre cas per repintar la pantalla. En cada execució pintarem la pilota recalculant les seves noves coordenades i així crearem el moviment.
  
Disposem de diverses llibreries:
+
Utilitzarem l'[http://qt-project.org/doc/qt-4.8/qtimer.html objecte QTimer de Qt]. Caldrà que l'inicialitzem en algun punt del codi (constructor), indicar on cridarà (connectar-lo al repaint), inicialitzar el temps d'intèrval i llançar-ho amb un ''start''.
* [http://docs.python.org/2/library/threading.html#timer-objects Threading lib (pròpia de Python)]: té l'avantatge que ve integrada i que no cal instal·lar res. En el nostre cas té diversos desavantatges:
+
 
** No té prou precisió temporal.
+
<syntaxhighlight lang="python">
** En realitat és un '''''timeout''''' és a dir, que s'executa un cop i prou. Nosaltres volem una crida cada cert interval de temps. És clar que podriem elaborar un timer repetitiu, però serà més senzill utilitzar el Timer de Qt.
+
class Pantalla(QWidget):
* Qt: http://doc.qt.digia.com/4.7/qtimer.html
+
    #...
** El QTimer és repetitiu, seleccionem el temps entre crides amb '''''setInterval()''''' (d'entrada recomanem cada 20 ms).
+
    def __init__(self):
** Per utilitzar-ho caldrà que connectem la '''SIGNAL ''timeout()''''' del timer al '''SLOT ''repaint()''''' del QWidget (pel nostre cas, Pantalla, si heu seguit l'exemple).
+
        #...
** Controlem el timer amb les funcions '''''start()''''' i '''''stop()'''''
+
        self.timer = QTimer() # creem el timer
 +
        self.timer.timeout.connect( self.repaint ) # connectem la signal timeout al metode de repintat
 +
        #...
 +
        self.timer.start() # engeguem el time
 +
 
 +
#...en algun altre punt del nostre codi...
 +
#... si volem aturar la partida...
 +
pantalla.timer.stop()
 +
#...
 +
 
 +
</syntaxhighlight>
 +
 
 
<br>
 
<br>
  

Revisió del 15:52, 19 gen 2015

Exercici de pilota rebotant dins d'una pantalla.

L'implementem en PyQt (Python amb les llibreries Qt).


Introducció

Cal haver fet abans l'exercici PyQt: pintar dintre d'un widget.

Tindrem d'entrada una pantalla com aquesta però enlloc del controlar la posició de la pilota controlarem la velocitat. La pilota es mourà i rebotarà per les parets.

Qt-piloteta1.png

Suggeriments per fer la pràctica

Cadascun d'aquests punts els anem aclarint més avall.

  1. Crear el timer i fer un print cada 100 ms
  2. Avançar la pilota, sense rebots. Podem deixar la posx i la posy en l'objecte Pantalla, tal i com ho teniem a la pràctica anterior.
  3. Crear objecte pilota i encapsular a dins els atributs i funcions descrits més avall.
  4. Gestionar els rebots dintre de l'objecte pilota.


Timers

Per poder moure la pilota necessitareu un Timer: un temporitzador que regularment faci una crida a una funció, en el nostre cas per repintar la pantalla. En cada execució pintarem la pilota recalculant les seves noves coordenades i així crearem el moviment.

Utilitzarem l'objecte QTimer de Qt. Caldrà que l'inicialitzem en algun punt del codi (constructor), indicar on cridarà (connectar-lo al repaint), inicialitzar el temps d'intèrval i llançar-ho amb un start.

class Pantalla(QWidget):
    #...
    def __init__(self):
        #...
        self.timer = QTimer() # creem el timer
        self.timer.timeout.connect( self.repaint ) # connectem la signal timeout al metode de repintat
        #...
        self.timer.start() # engeguem el time

#...en algun altre punt del nostre codi...
#... si volem aturar la partida...
pantalla.timer.stop()
#...


Objecte Pilota

Farem les coses bé. Crearem un objecte Pilota que contindrà els següents atributs.

float
  • posx
  • posy
  • velx
  • vely
  • maxVel (de moment no el fem servir, però indicarà la màxima velocitat de la pilota)
  • color (QColor, es dona en RGB)
  • tamany (radi de la pilota)

I tindrà els següents mètodes:

  • pinta ( QPainter )
  • actualitza_pos ( amplada, alçada )
  • setVelX ( valor )
  • setVelY ( valor )


L'objecte Pantalla tindrà un objecte Pilota a dins, que gestionarà el seu propi moviment i rebot dintre de actualitza_pos (li passarem l'amplada i alçada del widget Pantalla per adaptarnos al seu tamany i fer els rebots correctament). Per tant, ara a Pantalla.pinta() tindrem només:

  • Crear QPainter qp
  • pilota.actualitza_pos(...)
  • pilota.pinta( qp )

Connexions (però casi que millor ho deixeu pel final, de moment avanceu la pilota amb velocitat constant):

  • xslider -> setVelX
  • yslider -> setVelY


Gestió dels rebots

float

Dintre de la funció actualitza_pos( ample, alt ) de la pilota caldrà gestionar els rebots:

  • Incrementar posició segons velocitat
  • Controlar que la posició de la pilota no ha sobrepassat cap dels 4 límits de les parets. Si ho ha fet, canviem:
    • El signe (+ o -) de la velocitat.
    • Col·loquem la pilota en el límit per si ens hem passat.


Velocitat variable

Efectuem les connexions:

  • xslider -> setVelX
  • yslider -> setVelY

Recordatori: PyQt: connectant signals amb slots

I dintre d'aquests mètodes modifiquem la velocitat de la pilota. Veurem com canvia la trajectòria.

Connectem teclat amb els controls

Volem modificar la velocitat de la pilota també amb les tecles de cursor.

Ho pots fer amb aquest article: PyQt: Events de teclat

El pas següent pot ser pintar una raqueta per fer el joc del ping-pong. La pots controlar amb les tecles també.