XII. Doux comme un agneau▲
Dans cet exemple, on ajoute le contrôle de la puissance du canon.
XII-A. Analyse du code ligne par ligne▲
XII-A-1. t10/connonfield.h▲
Le CannonField possède les attributs force (puissance de tir) et angle (angle de tir), définis précédemment.
int
angle() const
{
return
currentAngle; }
int
force() const
{
return
currentForce; }
public
slots
:
void
setAngle(int
angle);
void
setForce(int
force);
signals
:
void
angleChanged(int
newAngle);
void
forceChanged(int
newForce);
L'interface de la puissance se définit de la même manière que celle de l'angle
private
:
QRect
cannonRect() const
;
La définition du cadre du canon se situe dans une fonction séparée.
int
currentAngle;
int
currentForce;
}
;
La puissance est stockée dans la variable currentForce.
XII-A-2. t10/cannonField.cpp▲
CannonField::
CannonField(QWidget
*
parent)
:
QWidget
(parent)
{
currentAngle =
45
;
currentForce =
0
;
setPalette(QPalette
(QColor
(250
, 250
, 200
)));
setAutoFillBackground(true
);
}
La puissance est initialisée à zéro.
void
CannonField::
setAngle(int
angle)
{
if
(angle <
5
)
angle =
5
;
if
(angle >
70
)
angle =
70
;
if
(currentAngle ==
angle)
return
;
currentAngle =
angle;
update(cannonRect());
emit
angleChanged(currentAngle);
}
On a fait quelques modifications dans la fonction setAngle(). Elle ne redessine que la portion du widget qui contient le canon.
void
CannonField::
setForce(int
force)
{
if
(force <
0
)
force =
0
;
if
(currentForce ==
force)
return
;
currentForce =
force;
emit
forceChanged(currentForce);
}
L'implémentation de setForce est similaire à celle de setAngle(). La seule différence réside dans le fait que la valeur de la puissance n'a pas à être représentée ; on n'a donc pas besoin, quand la puissance change, de redessiner le widget.
void
CannonField::
paintEvent(QPaintEvent
*
/* event */
)
{
QPainter
painter(this
);
painter.setPen(Qt
::
NoPen);
painter.setBrush(Qt
::
blue);
painter.translate(0
, height());
painter.drawPie(QRect
(-
35
, -
35
, 70
, 70
), 0
, 90
*
16
);
painter.rotate(-
currentAngle);
painter.drawRect(QRect
(30
, -
5
, 20
, 10
));
}
On dessine comme au chapitre XI.
QRect
CannonField::
cannonRect() const
{
QRect
result(0
, 0
, 50
, 50
);
result.moveBottomLeft(rect().bottomLeft());
return
result;
}
La fonction cannonRect() retourne le cadre contenant le canon dans les coordonnées relatives au widget. On crée d'abord un rectangle de dimensions 50 x 50 ; ensuite on le déplace jusqu'à ce que le coin inférieur gauche coïncide avec le coin inférieur gauche du widget.
La méthode QWidget::rect() retourne le cadre d'un QWidget dans ses propres coordonnées. Les coordonnées du coin supérieur gauche sont toujours (0,0).
XII-A-3. t10/main.cpp▲
MyWidget::
MyWidget(QWidget
*
parent)
:
QWidget
(parent)
{
Le constructeur demeure globalement le même : on a juste ajouté quelques détails.
LCDRange *
force =
new
LCDRange;
force->
setRange(10
, 50
);
On a ajouté un nouveau LCDRange qui va être utilisé pour indiquer la puissance.
connect
(force, SIGNAL
(valueChanged(int
)),
cannonField, SLOT
(setForce(int
)));
connect
(cannonField, SIGNAL
(forceChanged(int
)),
force, SLOT
(setValue(int
)));
On connecte un widget cannonField, comme on l'a fait pour le widget angle.
QVBoxLayout
*
leftLayout =
new
QVBoxLayout
;
leftLayout->
addWidget(angle);
leftLayout->
addWidget(force);
QGridLayout
*
gridLayout =
new
QGridLayout
;
gridLayout->
addWidget(quit, 0
, 0
);
gridLayout->
addLayout(leftLayout, 1
, 0
);
gridLayout->
addWidget(cannonField, 1
, 1
, 2
, 1
);
gridLayout->
setColumnStretch(1
, 10
);
Au chapitre IX, on avait placé le contrôle de l'angle dans la cellule du coin inférieur gauche. À présent, on voudrait deux widgets dans cette cellule. On crée donc une boîte de disposition verticale, on met cette boîte dans la cellule et on ajoute angle et force dans cette boîte.
force->
setValue(25
);
On initialise la puissance à 25.
XII-B. Exécuter l'application▲
On peut maintenant contrôler la valeur de la puissance.
XII-C. Exercices▲
Faire varier la taille du canon en fonction de la puissance.
Placer le canon dans le coin inférieur droit.
Essayez encore d'améliorer l'interface. Par exemple, faites en sorte que les touches + et – du clavier permettent d'augmenter ou de diminuer la puissance et que la touche entrée déclenche le tir. Si vous êtes troublé par le comportement des touches Left et Right, vous pouvez aussi le changer.
Remarque : réimplémentez QWidget::KeyPressEvent().