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

De Cacauet Wiki
Salta a la navegació Salta a la cerca
(Es crea la pàgina amb «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…».)
 
 
(Hi ha 7 revisions intermèdies del mateix usuari que no es mostren)
Línia 11: Línia 11:
 
[[Fitxer:Qt-piloteta1.png]]
 
[[Fitxer:Qt-piloteta1.png]]
  
 +
=== Suggeriments per fer la pràctica ===
 +
Cadascun d'aquests punts els anem aclarint més avall.
 +
# Crear el timer i fer un print cada 100 ms
 +
# 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.
 +
# Crear objecte pilota i encapsular a dins els atributs i funcions descrits més avall.
 +
# Gestionar els rebots dintre de l'objecte pilota.
 
<br>
 
<br>
  
Línia 16: 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( 200 ) # engeguem el timer (temps en ms)
 +
 
 +
#...en algun altre punt del nostre codi...
 +
#... si volem aturar la partida...
 +
pantalla.timer.stop()
 +
#...
 +
 
 +
</syntaxhighlight>
 +
 
 
<br>
 
<br>
  
 
== Objecte Pilota ==
 
== Objecte Pilota ==
Farem les coses bé. Crearem un objecte Pilota que contindrà els següents atributs:
+
Farem les coses bé. Crearem un objecte Pilota que contindrà els següents atributs.
 +
 
 +
[[Fitxer:Pilota-uml.png|float|right]]
 +
 
 
* posx
 
* posx
 
* posy
 
* posy
Línia 33: Línia 53:
 
* vely
 
* vely
 
* maxVel (de moment no el fem servir, però indicarà la màxima velocitat de la pilota)
 
* maxVel (de moment no el fem servir, però indicarà la màxima velocitat de la pilota)
* color
+
* color (QColor, es dona en RGB)
* tamany
+
* tamany (radi de la pilota)
  
 
I tindrà els següents mètodes:
 
I tindrà els següents mètodes:
Línia 46: Línia 66:
 
* Crear QPainter qp
 
* Crear QPainter qp
 
* pilota.actualitza_pos(...)
 
* pilota.actualitza_pos(...)
* pilota.pinnta( qp )
+
* pilota.pinta( qp )
  
 
Connexions (però casi que millor ho deixeu pel final, de moment avanceu la pilota amb velocitat constant):
 
Connexions (però casi que millor ho deixeu pel final, de moment avanceu la pilota amb velocitat constant):
Línia 54: Línia 74:
  
 
== Gestió dels rebots ==
 
== Gestió dels rebots ==
 +
[[Fitxer:Pilota-rebots.png|float|right]]
 +
 
Dintre de la funció '''actualitza_pos( ample, alt )''' de la pilota caldrà gestionar els rebots:
 
Dintre de la funció '''actualitza_pos( ample, alt )''' de la pilota caldrà gestionar els rebots:
 
* Incrementar posició segons velocitat
 
* Incrementar posició segons velocitat
Línia 65: Línia 87:
 
* xslider -> setVelX
 
* xslider -> setVelX
 
* yslider -> setVelY
 
* 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.
 
I dintre d'aquests mètodes modifiquem la velocitat de la pilota. Veurem com canvia la trajectòria.
  
== Connectem teclat amb els sliders ==
+
== Connectem teclat amb els controls ==
 
Volem modificar la velocitat de la pilota també amb les tecles de cursor.
 
Volem modificar la velocitat de la pilota també amb les tecles de cursor.
  
...TODO...
+
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é.
 +
 
 +
<br>

Revisió de 17:07, 19 gen 2015

Exercici de pilota rebotant dins d'una pantalla.

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


Introducció[modifica]

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[modifica]

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[modifica]

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( 200 ) # engeguem el timer (temps en ms)

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


Objecte Pilota[modifica]

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[modifica]

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[modifica]

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[modifica]

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é.