You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libtqt-perl/doc/fr/PerlQt.pod

1190 lines
37 KiB

=head1 Programmer avec PerlTQt
B<Germain Garand> traduit par B<St<53>phane Payrard>, r<>vis<69> et augment<6E> par l'auteur.
Ce document d<>crit l'interface Perl au toolkit TQt 3.x. Contacter
l'auteur <20> <germain@ebooksfrance.com> ou le traducteur <20>
<stef@mongueurs.net>. Vous trouverez le document original sur le site
L<perlqt.sourceforge.net|"http://perlqt.sourceforge.net">
=head1 Introduction
PerlTQt-3, cr<63>e par Ashley Winters, est une interface perl aux composants
graphiques (et non graphiques) fournis par TQt3.
Le toolkit TQt 3.0 auquel PerlTQt acc<63>de <20> <20>t<EFBFBD> <20>crit en C++ par la soci<63>t<EFBFBD>
Trolltech: L<Trolltech|"http://www.trolltech.com">.
PerlTQt3 est fond<6E> sur la librairie
L<SMOKE|"http://webcvs.kde.org/cgi-bin/cvsweb.cgi/kdebindings/smoke">,
une surcouche fine ind<6E>pendante du langage. Cette couche a <20>t<EFBFBD> g<>n<EFBFBD>r<EFBFBD>e
<EFBFBD> partir des fichiers d'en t<>te de TQt par le
L<kalyptus|"http://webcvs.kde.org/cgi-bin/cvsweb.cgi/kdebindings/kalyptus">
de Richard Dale gr<67>ce au module de David Faure.
Le pr<70>sent document d<>crit les principes de la programmation PerlTQt.
Vous devez avoir des notions de programmation orient<6E>e objet en Perl pour le
lire. Une connaissance de C++ est recommand<6E>e mais non requise. Avec
celle de l'anglais, elle vous facilitera la consultation des L<manuels
en ligne de TQt|"http://doc.trolltech.com">. Ladite documentation est
la seule r<>f<EFBFBD>rence qui fasse autorit<69>.
Si TQt est install<6C> sur votre syst<73>me, sa documentation l'est
certainement aussi : voyez le programme $TQTDIR/bin/assistant.
=head1 Installation
=head2 Conditions requises
Pour compiler et utiliser PerlTQt, vous devez avoir:
=over 4
=item *
un syst<73>me conforme <20> la norme POSIX.
=item *
L<Perl E<gt>= v5.6.0|"http://www.perl.org">
=item *
L<TQt E<gt>=
v3.0|"http://www.trolltech.com/developer/download/qt-x11.html">
=item *
L<SmokeTQt
1.2.1|"http://webcvs.kde.org/cgi-bin/cvsweb.cgi/kdebindings/smoke"> La
librarie SMOKE (Scripting Meta Object Kompiler) fait partie du module
L<KDE|"http://www.kde.org">'s B<kdebindings>. Vous pouvez v<>rifier si
une version pr<70>compil<69>e de ce module existe pour votre syst<73>me. Mais
perlTQt inclut une copie, donc la version pr<70>compil<69>e n'est pas
n<EFBFBD>cessaire.
=item *
Les outils GNU : automake(>=1.5), autoconf (>=2.13), aclocal...
=back
L'installation de Perl et de TQt sont en dehors du sujet du pr<70>sent
document. Se r<>f<EFBFBD>rer aux documentations respectives de ces logiciels.
=head2 Compilation de PerlTQt
Les instructions de cette section pr<70>supposent que le r<>pertoire courant est
le r<>pertoire racine de l'arborescence des sources de PerlTQt.
PerlTQt utilise le syst<73>me GNU Autoconf, mais il est pr<70>f<EFBFBD>rable de le lancer via
le script standard C<Makefile.PL> :
perl Makefile.PL
B<N.B :> Si la variable d'environnement B<TQTDIR> n'est pas d<>finie, vous devrez
peut-<2D>tre sp<73>cifier manuellement l'emplacement de TQt <20> l'aide de l'option :
--with-qtdir=/emplacement/de/TQt
Si la biblioth<74>que SMOKE est manquante, C<configure> g<>n<EFBFBD>rera ses sources dans
un sous-r<>pertoire.
make
make install
Cela installera PerlTQt, Puic et les utilitaires pqtsh et pqtapi.
Le lieu d'installation privil<69>gi<67> de SMOKE et de PUIC est le syst<73>me de
fichiers de KDE3. Si KDE3 n'est pas install<6C> (ou que la variable TDEDIR n'est pas
d<EFBFBD>finie), sp<73>cifier ce lieu avec l'option C<--prefix> de C<configure>'s. Ainsi :
perl Makefile.PL --prefix=/usr
=head2 Installation avec les droits d'utilisateur
Pour r<>aliser une installation locale, sans les droits de super-utilisateur,
suivez les instructions suivantes :
=over 4
=item *
R<EFBFBD>alisez tout d'abord une configuration normale, en sp<73>cifiant le pr<70>fixe de la hi<68>rarchie de fichier
dans laquelle la biblioth<74>que Smoke et l'ex<65>cutable 'puic' seront install<6C>s :
perl Makefile.PL --prefix=~
Ceci installera Smoke dans ~/lib et puic dans ~/bin
=item *
Reconfigurez le module PerlTQt pour qu'il ne s'installe pas dans la hi<68>rarchie Perl ordinaire :
cd PerlTQt
perl Makefile.PL PREFIX=~
cd ..
Attention : il ne s'agit pas du Makefile.PL situ<74> <20> la racine de l'arborescence mais bien de celui
situ<EFBFBD> dans le sous-r<>pertoire PerlTQt
=item *
Lancez la compilation et l'installation
make && make install
Pour ex<65>cuter des programmes PerlTQt, il vous faudra d<>sormais indiquer <20> Perl l'emplacement de cette hi<68>rarchie externe,
<EFBFBD> l'aide d'une ligne de la forme :
perl -Mlib="~/local/lib/perl/5.x.x" programme.pl
o<EFBFBD> 5.x.x repr<70>sente la version de Perl utilis<69>e, ligne qui peut <20>galement <20>tre plac<61>e en t<>te de programme :
use lib qw( ~/local/lib/perl/5.x.x );
=back
=head1 Anatomie de PerlTQt
Un programme TQt typique utilisant des composants GUI est fond<6E> sur une
boucle <20>v<EFBFBD>nementielle.
Il ne se comporte pas comme une suite s<>quentielle
d'instructions o<> vous devriez g<>rer vous-m<>me chaque <20>v<EFBFBD>nement (tels
que le clic de la souris ou l'enfoncement d'une touche).
Au lieu de cela, vous cr<63>ez un objet B<TQt::Application> et les composants
du GUI qu'il utilise, puis vous d<>finissez les m<>thodes d'objet <20> appeler
lors de l'occurrence d'un <20>v<EFBFBD>nement, puis d<>marrez la boucle <20>v<EFBFBD>nementielle.
C'est tout. TQt g<>rera les <20>v<EFBFBD>nements et les dirigera vers les
routines appropri<72>es.
Voyons un programme PerlTQt minimal.
=head2 Hello World
1: use TQt;
2: my $a = TQt::Application(\@ARGV);
3: my $hello = TQt::PushButton("Hello World!", undef);
4: $hello->resize(160, 25);
5: $a->setMainWidget($hello);
6: $hello->show;
7: exit $a->exec;
=for html
<br/>
<div class='image'><img src="../images/ex1.png"/></div>
Ce programme charge d'abord le module TQt [line 1] puis cr<63>e l'objet
application B<$a> en lui passant une r<>f<EFBFBD>rence au tableau C<@ARGV>
contenant les arguments de la ligne de commande [l.2]. Cet objet
application est unique pour un interpr<70>teur Perl donn<6E> et peut <20>tre
ensuite acc<63>d<EFBFBD> par la fonction pure B<TQt::app()>.
La ligne 3, cr<63>e un PushButton orphelin (c.<2E>.d sans parent: non
contenu dans un autre widget) dont nous passons la valeur B<undef>
comme argument pour le parent. B<undef> est l'<27>quivalent perlTQt d'un
pointeur null en C++.
Apr<EFBFBD>s les instructions de "mise en page" [l.4], nous indiquons <20>
l'objet application que le widget principal est ce
PushButton... Ainsi, il saura que fermer la fen<65>tre associ<63>e <20> ce
widget signifie: I<sortir de l'application>.
Pour rendre ce widget visible (qui est par d<>faut cach<63>), on
appelle la m<>thode B<show> [l.6] et lance la boucle
<EFBFBD>v<EFBFBD>nementielle [l.7].
B<Sommaire de la syntaxe :>
=over 4
=item 1
Les classes PerlTQt sont accessibles par le pr<70>fixe B<TQt::> au lieu du
B<Q> initial des classes TQt en C++. En consultant la L<documentation
TQt|"http://doc.trolltech.com">, vous devez donc mentalement changer le
nom d'une clasee B<TQFoo> en B<TQt::Foo>.
=item 2
De mani<6E>re similaire <20> C++, un objet est cr<63><72> par l'appel d'un
B<constructeur> de m<>me nom que la classe dont il est une m<>thode.
Vous ne devez donc pas dire C<new TQt::Foo> ou C<TQt::Foo-E<gt>new()>
contrairement <20> l'usage commun en Perl.
Dites simplement:
my $object = TQt::<classname>(arg_1, ..., arg_n);
Un constructeur sans argument s'<27>nonce encore plus bri<72>vement :
my $object = TQt::<classname>;
=item 3
Comme il a d<>j<EFBFBD> <20>t<EFBFBD> dit, l'<27>quivalent Perl d'un pointeur C++ est le mot-cl<63>
Perl B<undef>.
Les pointeurs sont les arguments pr<70>c<EFBFBD>d<EFBFBD>s par le caract<63>re B<*> dans la
documentation TQt (Par exemple: "C<TQWidget* widget>").
=back
=head2 L'h<>ritage et les objets
Avant d'expliquer comment les routines Perl peuvent <20>tre appel<65>es de TQt,
parlons du m<>canisme d'h<>ritage vu de PerlTQt.
PerlTQt est con<6F>u pour allier la simplicit<69> de TQt <20> la puissance et <20> la
flexibilit<EFBFBD> de Perl. Pour ce faire, PerlTQt <20>tend le paradigme objet de
Perl pour mimer TQt et son m<>canisme de B<m<>taobjets>.
=head3 Un Widget personnalis<69>
R<EFBFBD><EFBFBD>crivons le programme "Hello World!" avec une version personnalis<69>e
de PushButton:
1: use strict;
2:
3: package Button;
4: use TQt;
5: use TQt::isa qw(TQt::PushButton);
6:
7: sub NEW
8: {
9: shift->SUPER::NEW(@_[0..2]);
10: resize(130, 40);
11: }
12:
13: 1;
14:
15: package main;
16:
17: use TQt;
18: use Button;
19:
20: my $a = TQt::Application(\@ARGV);
21: my $w = Button("Hello World!", undef);
22: $a->setMainWidget($w);
23: $w->show;
24: exit $a->exec;
Pour implanter notre propre version de PushButton, nous cr<63>ons un nouveau
package [l.3] et importons TQt [l.4].
Nous utilisons le pragma C<TQt::isa> [l.5] pour d<>clarer notre widget
comme sous-classe de PushButton. Ce pragma accepte une liste de une ou
plusieurs classes dont d<>rive la classe <20> d<>finir.
Cr<EFBFBD>ons maintenant un constructeur pour notre nouveau widget
en <20>crivant une routine appel<65>e B<NEW> I<(notez les majuscules qui
marquent une m<>thode diff<66>rente du constructeur "new" usuel)>.
Le constructeur PerlTQt est appel<65> B<implicitement> I<comme ligne 21>.
Note widget doit d'abord appeler le constructeur de sa classe de base
(ici: TQt::PushButton) <20> la ligne 9, avec tous les arguments que nous
avons re<72>us.
Nous cr<63>ons ainsi un objet instance de notre classe. Cette objet est
accessible par la fonction B<this> (Attention: ce n'est pas la
variable C<$this> mais simplement C<this>).
Chaque fois que nous invoquons une m<>thode <20> partir de notre package
nous pouvons <20>crire indiff<66>remment C<method()> ou
C<this-E<gt>method()>;
=head3 L'utilisation d'attributs
Lors de la construction d'un objet composite, vous pouvez simplement cr<63>er
ses diff<66>rents composants <20> l'int<6E>rieur de variables de scope lexical
(c.<2E>.d d<>clar<61>es par B<my>) puisque les widgets sont seulement d<>truits
par leur parent et non n<>cessairement quand leur conteneur dispara<72>t
du scope.
En d'autres termes, PerlTQt utilise un syst<73>me de comptage de
r<EFBFBD>f<EFBFBD>rences pour g<>rer la destruction des objets.
Souvent cependant, vous souhaiterez acc<63>der aux composants de votre objet depuis
un tout autre endroit que celui o<> vous l'avez cr<63><72> (par exemple pour modifier une
l<EFBFBD>gende de bouton dynamiquement). Dans ce cas, la syntaxe traditionnelle de perl
propose de stocker une r<>f<EFBFBD>rence <20> ces composants dans la table associative (hash) de
l'objet lui-m<>me. Mais cette syntaxe s'av<61>re peu pratique <20> l'usage et beaucoup
trop libre - il n'y a pas de v<>rification <20> la compilation de sorte que vous pouvez
acc<EFBFBD>der <20> des clefs non existantes sans d<>clencher d'erreur.
En lieu et place de cette syntaxe, PerlTQt introduit le concept d'B<attributs>.
Les attributs sont de simples variables perl, <20>crites sans le signe dollar initial, et
pouvant contenir toute donn<6E>e qui est une propri<72>t<EFBFBD> de votre objet.
Leur principal avantage est de fournir une syntaxe tr<74>s rapide et v<>rifiable <20> la compilation.
Pour d<>finir et pouvoir utiliser de nouveaux attributs, il suffit d'utiliser
le pragma C<use TQt::attributes>, suivi d'une liste des noms d'attributs souhait<69>s.
Ainsi:
1: use strict;
2:
3: package Button;
4: use TQt;
5: use TQt::isa qw(TQt::PushButton);
6: use TQt::attributes qw(
7: itsTime
8: pData
9: );
10:
11: sub NEW
12: {
13: shift->SUPER::NEW(@_[0..2]);
14: itsTime = TQt::Time;
15: itsTime->start;
16: pData->{'key'} = " Foo ";
17: }
18:
19: sub resizeEvent
20: {
21: setText( "w: ". width() ." h: ". height() .
22: "\nt: ". itsTime->elapsed . pData->{'key'} );
23: }
24:
25: 1;
=for html
<br/>
<div class='image'><img src="../images/ex2.png"/></div>
L'attribut itsTime est d<>clar<61> <20> la ligne 7 et initialis<69> par un objet C<TQt::Time>
<EFBFBD> la ligne 14.
Puisque nous r<>impl<70>mentons la fonction virtuelle "resizeEvent"
[l.19], chaque fois que le widget principal est redimensionn<6E>, cette
fonction "resizeEvent" sera d<>clench<63>e et le texte de notre Button mis
<EFBFBD> jour avec les valeurs venant de l'objet [1.21] et les attributs que
nous avons d<>finis [1.22].
B<R<>capitulation>
=over 4
=item *
Pour h<>riter d'une classe TQt, un package doit contenir un
pragma C<use TQt::isa>.
Ainsi:
use TQt::isa "TQt::widget";
=item *
Le constructeur d'objet est nomm<6D> B<NEW> et est appel<65> implicitement.
Vous ne devez donc pas dire:
my $o = MyButton->NEW("Hello");
Mais bien :
my $o = MyButton("Hello");
=item *
A l'int<6E>rieur d'un package, on acc<63>de l'instance courante par la
fonction B<this>.
Quand une fonction membre est appel<65>e, les arguments sont accessibles
par le tableau B<@_>, mais le premier <20>l<EFBFBD>ment de B<@_> n'est pas une
r<EFBFBD>f<EFBFBD>rence <20> l'objet contrairement <20> l'usage commun en Perl.
Vous ne pouvez donc pas dire :
sub myMember
{
my $moi = shift;
my $arg = shift;
$arg->doThat($moi);
$moi->doIt;
}
<EFBFBD>crivez plut<75>t :
sub myMember
{
my $arg = shift;
$arg->doThat(this);
doIt();
}
De plus, si vous voulez appeler une m<>thode dans une classe de base <20>
partir d'une classe d<>riv<69>e, utilisez l'attribut sp<73>cial SUPER :
sub exemple
{
print "Appel de la m<>thode 'exemple' dans la classe de base";
SUPER->exemple(@_)
}
Notez aussi que la construction :
this->SUPER::Exemple(@_);
est possible, mais qu'elle passe l'objet comme premier argument.
=item *
Lorsque vous devez stocker dans votre package un objet contenu, vous
devez le d<>finir comme B<attribut> :
use TQt::attributes qw(
firstAttribute
...
lastAttribute);
Il sera alors disponible comme accesseur :
firstAttribute = myContainedWidget( this );
firstAttribute->resize( 100, 100 );
B<NB:> Pour ceux qui souhaitent en savoir plus, les attributs sont impl<70>ment<6E>s
<EFBFBD> l'aide de sub lvalue, c'est <20> dire de fonctions assignables.
En interne, elles ne font que pointer sur la clef de hachage correspondante dans
l'objet B<this>, ce qui rend les tournures "unAttribut->fonction()" et
"this->{'unAttribut'}->fonction()" strictement <20>quivalentes
(si ce n'est que la premi<6D>re est v<>rifi<66>e au moment de la compilation).
=item *
Pour r<>impl<70>menter une B<fonction virtuelle>, cr<63>ez simplement une
B<sub> de m<>me nom que cette fonction.
Les fonctions virtuelles existantes sont marqu<71>es comme telles dans
la documentation de TQt (ce sont les m<>thodes pr<70>c<EFBFBD>d<EFBFBD>es du mot clef "virtual").
Vous pouvez visualiser les noms de m<>thodes virtuelles que TQt tentera d'appeler
dans votre classe en pla<6C>ant C<use TQt::debug qw|virtual|> en t<>te de
votre programme.
=back
=head2 Signaux et Slots
Voyons maintenant comment les objets TQt peuvent communiquer entre eux
de mani<6E>re <20> ce qu'un <20>v<EFBFBD>nement concernant un objet puisse d<>clencher
l'ex<65>cution d'une routine en un quelconque endroit de votre programme.
Dans d'autres toolkits, les callbacks (appels en retour) sont g<>n<EFBFBD>ralement
utilis<EFBFBD>s <20> cet effet. Mais TQt dispose d'un m<>canisme beaucoup plus puissant
et plus flexible : les B<Signaux et Slots>.
On peut se le repr<70>senter comme le cablage entre les composants d'une
cha<EFBFBD>ne Hi-Fi. Un amplificateur, par exemple, <20>met des signaux de sortie
sans chercher <20> savoir si des enceintes lui sont connect<63>es ou non.
Un magn<67>tophone peut attendre un signal sur sa prise d'entr<74>e
pour commencer <20> enregistrer, et il ne cherchera pas <20> savoir s'il est
l'unique destinataire de ce signal ou si ce dernier est aussi re<72>u par un graveur de CD
ou <20>cout<75> au casque.
Un composant TQt se comporte comme notre amplificateur ou notre
magn<EFBFBD>tophone. Il a des sorties ou B<Signaux> et des entr<74>es ou
B<Slots>. Chaque sortie (signal) est connectable <20> un nombre illimit<69>
d'entr<74>es (slots). La sortie d'un composant peut <20>tre potentiellement
branch<EFBFBD>e <20> toute entr<74>e d'un composant (y compris lui-m<>me),
La syntaxe de ce syst<73>me de connexion est soit:
TQt::Object::connect( envoyeur, TQT_SIGNAL 'mon_signal(types_d_arguments)',
recepteur, TQT_SLOT 'monslot(types_d_arguments)');
soit:
unObjet->connect( envoyeur, TQT_SIGNAL 'mon_signal(types_d_arguments)',
SLOT 'monslot(types_d_arguments)');
Dans le second cas, le r<>cepteur est omis car c'est l'objet lui-m<>me,
Ce m<>canisme est extensible <20> volont<6E> par la d<>claration de nouveaux Signaux et
Slots par l'usage des pragma C<use TQt::signals> et C<use TQt::slots>
(voir aussi la deuxi<78>me syntaxe d<>crite plus bas).
Chaque slot d<>clar<61> appellera la routine correspondante de votre
objet. Chaque signal d<>clar<61> peut <20>tre d<>clench<63> via le mot-cl<63> B<emit>.
B<R<><52>crivons encore notre exemple pour illustrer nos propos :>
1: use strict;
2:
3: package Button;
4: use TQt;
5: use TQt::isa qw(TQt::PushButton);
6: use TQt::attributes qw(itsTime);
7: use TQt::slots
8: aEteClicke => [],
9: changement => ['int', 'int'];
10: use TQt::signals
11: changeLe => ['int', 'int'];
12:
13: sub NEW
14: {
15: shift->SUPER::NEW(@_[0..2]);
16: itsTime = TQt::Time;
17: itsTime->start;
18: this->connect(this, TQT_SIGNAL 'clicked()', TQT_SLOT 'aEteClicke()');
19: this->connect(this, TQT_SIGNAL 'changeLe(int,int)', TQT_SLOT 'changement(int,int)');
20: }
21:
22: sub aEteClicke
23: {
24: my $w = width();
25: my $h = height();
26: setText( "w: $w h: $h\nt: ". itsTime->elapsed );
27: emit changeLe($w, $h);
28: }
29:
30: sub changement
31: {
32: my ($w, $h) = @_;
33: print STDERR "w: $w h: $h \n";
34: }
35:
36: 1;
Nous d<>finissons dans ce package deux nouveaux slots et un nouveau signal.
La documentation TQt nous dit que tout PushButton click<63> <20>met un signal
C<clicked()> ; nous le connectons donc <20> notre nouveau slot [ligne 18].
Nous connectons aussi notre signal C<ChangeLe> <20> notre slot
C<changement>.
Ainsi, quand on appuie (clique) sur notre Button , le signal
C<clicked()> est <20>mit et d<>clenche le slot C<aEteClicke()>.
C<aEteClicke()> <20>met <20> son tour le signal C<changeLe(int,int)>[l.27],
appelant de ce fait le slot C<changement(int,int)>, avec deux arguments.
Enfin, il existe une syntaxe alternative introduite dans PerlTQt-3.008 :
sub un_slot : TQT_SLOT(int, TQString)
{
$int = shift;
$string = shift;
# faire quelque chose
}
et
sub un_signal : TQT_SIGNAL(TQString);
Cette syntaxe est parfaitement compatible avec la d<>claration par le biais de
C<use TQt::signals> et C<use TQt::slots>.
Il peut d'ailleurs d'av<61>rer tr<74>s profitable pour la clart<72> du programme de d<>clarer tout d'abord
les signaux/slots au moyen de C<use TQt::slots/signals>, puis de rappeler cette d<>claration au niveau de
l'impl<70>mentation <20> l'aide de la seconde syntaxe.
Les d<>clarations seront alors v<>rifi<66>es <20> la compilation, et le moindre conflit
g<EFBFBD>n<EFBFBD>rera un avertissement.
=head1 D<>veloppement rapide (RAD) avec TQt Designer et Puic
=head2 Introduction
=over 4
=item * N.B:
Depuis la version 3.008, il existe un plugin sp<73>cifique <20> PerlTQt pour TQt Designer.
Ce plugin (disponible sur les pages internet du projet) apporte le confort d'une int<6E>gration pouss<73>e,
la coloration syntaxique Perl, la compl<70>tion automatique, et permet de lancer et d<>boguer un projet
sans quitter l'interface du Designer.
Ce qui suit reste n<>anmoins parfaitement valable pour ce qui est de l'utilisation de puic en ligne de commande,
et pour l'utilisation de TQt Designer I<sans> le plugin sp<73>cifique.
=back
Aussi puissant et intuitif que soit TQt, <20>crire une GUI compl<70>te reste un exercice
fastidieux.
Heureusement, TQt est fourni avec un constructeur de GUI sophistiqu<71>
appel<EFBFBD> TQt Designer qui est quasiment un environnement de d<>veloppement
int<EFBFBD>gr<EFBFBD>. Il comporte la gestion de Projets, la cr<63>ation d'un GUI par
des actions de "drag and drop", un butineur d'objet complet,
l'interconnexion graphique de signaux et de slots, et plus encore.
L'information g<>n<EFBFBD>r<EFBFBD>e par TQt Designer's est en format XML et peut donc
<EFBFBD>tre pars<72>e par diff<66>rentes commandes comme dont B<puic> (le
compilateur d'interface utilisateur PerlTQt).
Supposons que vous avez d<>ja construit un fichier d'interface avec
TQt Designer, la transcription en un programme PerlTQt se fait par
la simple ex<65>cution de la commande :
puic -x -o program.pl program.ui
Cela g<>n<EFBFBD>rera le package d<>fini dans votre fichier ui et un package
principal <20> fins de test,
Vous pouvez pr<70>f<EFBFBD>rer :
puic -o package.pm program.ui
Cela ne g<>n<EFBFBD>rera que le package qui pourra <20>tre utilis<69> par un programme s<>par<61>.
=head2 Inclure des Images
Il y a deux mani<6E>res d'inclure des B<images ou ic<69>nes>:
=over 4
=item * Inclusion Inline
A cette fin, nous devons s<>lectionner "Edit->Form
Settings->Pixmaps->Save inline" dans TQt Designer et executer ensuite:
puic -x -o F<program.pl> F<program.ui>
=item * Image Collection
Cette strat<61>gie est plus complexe, mais plus propre et plus puissante.
puic -o F<Collection.pm> -embed F<unique_identifier> F<image-1> ... F<image-n>
Ajoutez l'instruction C<use Collection.pm> dans le package principal
de votre programme.
Si vous avez cr<63><72> un fichier projet dans TQt Designer et ajout<75> toutes
les images dans un groupe (par "Project->Image Collection"), vous
disposez ensuite de ces images dans le r<>pertoire o<> votre fichier
projet (*.pro) est stock<63>, dans le sous-r<>pertoire B<image>. Vous pouvez
alors g<>n<EFBFBD>rer la collection d'images par:
puic -o F<Collection.pm> -embed F<identifier> images/*
Vous pouvez utiliser autant de collections d'images que vous voulez
dans un programme en ajoutant simplement une instruction B<use>
pour chaque collection.
=back
=head2 Travailler avec des fichiers B<.ui>
Souvent, vous voudrez reg<65>n<EFBFBD>rez votre interface utilisateur <20>
<EFBFBD> cause d'une modification ou extension de votre design initial.
C'est donc une mauvais id<69>e d'<27>crire votre code dans le fichier Perl
autog<EFBFBD>n<EFBFBD>r<EFBFBD> car vous risquerez d'<27>craser le code que vous avez <20>crit
manuellement ou vous devrez faire des copier-coller intensifs.
Voici une meilleure m<>thode :
=over 4
=item * <20>crire l'impl<70>mentation de slots dans le Designer
Dans TQt Designer, selectionnez l'onglet I<Source> dans l'explorateur
d'objets (B<Object Explorer>). Vous pouvez ainsi voir repr<70>sent<6E>es
sous forme d'arbre les classes que vous avez g<>n<EFBFBD>r<EFBFBD>es. Maintenant, si
vous cliquez deux fois sur l'entr<74>e I<Slots/public>,
un dialogue vous demande si vous voulez cr<63>er un nouveau slot pour
votre module. Une fois cela fait, le nouveau slot apparait <20>
l'int<6E>rieur de l'arbre l'explorateur d'objet; cliquer dessus vous
am<EFBFBD>nera <20> votre fichier B<E<lt>Votre ClasseE<gt>.ui.h> o<> vous pouvez
<EFBFBD>crire l'impl<70>mentation de votre slot.
Par d<>faut, il devrait ressembler <20> ceci :
void Form1::newSlot()
{
}
La d<>claration du slot est r<>ellement du code C++, mais ignorons cela
et <20>crivons du code Perl entre les deux accolades en faisant bien
attention d'indenter notre code avec au moins un espace.
void Form1::newSlot()
{
print STDERR "Hello world from Form1::newSlot();
if(this->foo())
{
# faire quelque chose
}
}
Notre code Perl ainsi <20>crit sera sauv<75> dans le fichier ui.h et
B<puic> prendra soin de le placer dans notre programme final.
Ici, apr<70>s l'ex<65>cution de B<puic> sur le ficier Form1.ui, vous
devriez avoir:
sub newSlot
{
print STDERR "Hello world from Form1::newSlot();
if(this->foo())
{
# faire quelque chose
}
}
=item * Sous-classez votre GUI
En utilisant l'option I<-subimpl> de B<puic>, vous pouvez g<>n<EFBFBD>rer un
module d<>riv<69> qui h<>rite l'interface utilisateur originelle.
Typiquement, vous g<>n<EFBFBD>rez le module d<>riv<69> une fois, et <20>crivez votre
code dans ce module d<>riv<69>. Ainsi, quand vous devez modifier votre
module GUI, reg<65>n<EFBFBD>rez le module dont il d<>rive et il h<>ritera les
changements.
Pour g<>n<EFBFBD>rer le module de base :
puic -o Form1.pm form1.ui
(fa<66>tes cela aussi souvent que n<>cessaire: n'<27>ditez jamais
manuellement form1.ui puisqu'il serait <20>cras<61>)
Pour g<>n<EFBFBD>rer le GUI d<>riv<69> :
puic -o Form2.pm -subimpl Form2 form1.ui
ou
puic -o program.pl -x -subimpl Form2 form1.ui
(faites cela une fois et travaillez avec le fichier r<>sultant)
=back
=head1 Autres outils de d<>veloppement
PerlTQt comprend <20>galement deux programmes pouvant vous aider <20> ma<6D>triser l'API de TQt :
=head2 pqtapi
pqtapi est un outil d'introspection en ligne de commande.
utilisation: pqtapi [-r <re>] [<class>]
options:
-r <re> : chercher les m<>thodes correspondant <20> l'expression r<>guli<6C>re <re>
-i : avec -r, effectue une recherche insensible <20> la casse
-v : afficher les versions de PerlTQt et de TQt
-h : afficher ce message d'aide
ex:
$>pqtapi -ir 'setpoint.* int'
void TQCanvasLine::setPoints(int, int, int, int)
void TQPointArray::setPoint(uint, int, int)
=head2 pqtsh
B<pqtsh> est un shell graphique permettant de tester l'API de mani<6E>re interactive.
Un exemple dynamique est accessible dans l'entr<74>e de menu C<Help-E<gt>Example>.
=for html
<br/>
<div class='image'><img src="../images/pqtsh.png"/></div>
=head1 Limitations
Les classes <20> mod<6F>le (templates) ne sont pas encore accessibles par PerlTQt.
En revanche, les classes d<>riv<69>es de classes <20> mod<6F>le sont disponibles.
Vous pouvez reconna<6E>tre ce type de classe en ce que leurs arguments comprennent un type g<>n<EFBFBD>rique plac<61> entre
les signes "<" et ">".
ex:
TQDictIterator ( const TQDict<type> & dict )
=head1 Cr<43>dits
PerlTQt-3 est (c) 2002 Ashley Winters (et (c) 2003 Germain Garand)
Kalyptus et l'engin de g<>n<EFBFBD>ration Smoke sont (c) David Faure and Richard Dale
Puic is (c) TrollTech AS., Phil Thompson et Germain Garand,
Ledit logiciel est d<>livr<76> sous la GNU Public Licence v.2 or later.
=head1 Appendice: Les conventions de C++ et leur traduction en Perl
Lorsque vous voulez utiliser depuis PerlTQt une classe ou m<>thode d<>crite
dans la L<documentation|"http://doc.trolltech.com"> TQt (voyez aussi le programme
$TQTDIR/bin/assistant livr<76> avec TQt), vous devez suivre des r<>gles de translation simples.
=over 4
=item Noms de classe
=over 4
=item *
Les noms de classes utilisent le pr<70>fixe B<TQt::> au lieu de B<Q> pour
<EFBFBD>tre conforme <20> l'usage Perl. Ainsi: TQComboBox est nomm<6D> TQt::ComboBox
dans PerlTQt.
=back
=item Fonctions
=over 4
=item *
Les fonctions d<>crites comme B<static> sont acc<63>d<EFBFBD>es directement et non
<EFBFBD> travers un objet. Ainsi la fonction statique Foo de la classe B<TQBar>
peut <20>tre acc<63>d<EFBFBD>e de PerlTQt par
TQt::Bar::Foo( arg-1,...,arg-n);
=item *
Les fonctions d<>crites comme B<members> ou B<Signals> sont
accessibles <20> travers l'objet par l'op<6F>rateur
B<-E<gt>> .
Par exemple:
$widget->show;
Il n'y a pas de diff<66>rence fondamentale entre les m<>thodes et les
signaux, n<>anmoins PerlTQt fournit le mot-cl<63> B<emit> comme une
mn<EFBFBD>monique pratique pour rendre clair que vous <20>mettez un signal :
emit $button->clicked;
=back
=item Arguments
=over 4
=item * Par valeur
Lorsqu'un argument n'est pas pr<70>c<EFBFBD>d<EFBFBD> par un des caract<63>res B<&> or
B<*>, il est pass<73> par valeur. Pour tous les types basiques tels que
int, char, float and double, PerlTQt convertira automatiquement les
valeurs lit<69>rales et scalaires dans le type correspondants C++.
Ainsi pour le prototype d'un constructeur <20>crit dans la documentation
comme ceci:
TQSize ( int w, int h )
Vous <20>crirez :
TQt::Size(8, 12);
=item * Par r<>f<EFBFBD>rence
Lorsqu'un argument est pr<70>c<EFBFBD>d<EFBFBD> par le caract<63>re B<&>, Il est une
r<EFBFBD>f<EFBFBD>rence <20> un objet ou <20> un type. Vous pouvez alors fournir un nom de
variable ou un objet temporaire :
$keyseq = TQt::keySequence( &TQt::CTRL + &TQt::F3 );
$widget->setAccel( $keyseq );
ou
$widget->setAccel(TQt::keySequence( &TQt::CTRL + &TQt::F3 );
Si l'argument n'est I<pas> qualifi<66> par B<const> (constante), l'argument
est un objet qui peut <20>tre alt<6C>r<EFBFBD> par la m<>thode, vous devez
donc passer une variable.
=item * Par pointeur
Lorsqu'un argument est pr<70>c<EFBFBD>d<EFBFBD> par le caract<63>re B<*>,
un pointeur vers un objet ou un type est attendu. En PerlTQt, vous
pouvez fournir un nom de variable ou le mot cl<63> B<undef> <20> la place
du pointer Null.
De plus, si l'argument est const, l'objet pass<73> en argument est en
lecture seule: il ne peut pas <20>tre modifi<66>.
=back
=item <20>num<75>rations
Les <20>numerations sont une forme d'alias pour des valeurs num<75>riques
dont il serait autrement difficile de se souvenir:
Exemple C++:
enum Strange { Apple, Orange, Lemon }
Ici, C<Strange> est le type (au sens de C++) de l'<27>num<75>ration, et
C<Apple>, C<Orange> et
C<Lemon> ses valeurs possible , qui sont des aliases pour des
nombres (ici 0, 1 et 2)
L'acc<63>s aux valeurs d'<27>num<75>ration en Perl TQt est un appel
de fonction statique.
Donc, si vous voulez <20>viter des prbl<62>mes de lisibilit<69>, nous vous
recommandons l'usage d'une syntaxe alternative d'appel de fonction
pour marquer l'utilisation d'un alias d'<27>num<75>ration: C<&fonction>.
Revenons <20> notre exemple C<Strange>.
Si nous rencontrons sa d<>finition dans la classe C<TQFruits>, vous
<EFBFBD>crirez en PerlTQt :
$pomme_plus_orange = &TQt::Fruit::Pomme + &TQt::Fruit::Orange;
=item Op<4F>rateurs
Dans PerlTQt, la B<surcharge d'op<6F>rateurs> fonctionne de mani<6E>re transparente.
Si un op<6F>rateur est surcharg<72> dans une classe TQt (ce qui signifie que son utilisation
d<EFBFBD>clenchera un appel de m<>thode, au lieu d'utiliser l'op<6F>rateur g<>n<EFBFBD>rique)
il sera <20>galement surcharg<72> dans PerlTQt.
ex-1: surcharge de '+='
$p1 = TQt::Point(10, 10)
$p2 = TQt::Point(30,40)
$p2 += $p1; # $p2 devient (40,50)
ex-2: surcharge de '<<'
$f = TQt::File("example");
$f->open( IO_WriteOnly ); # voir l'entr<74>e 'Constantes' plus bas
$s = TQt::TextStream( $f );
$s << "Que faire avec " << 12 << " pommes ?";
B<Exception notable> : le constructeur de copie (signe <20>gal, '=') n'est jamais surcharg<72>,
attendu qu'il ne pourrait fonctionner que partiellement et que le paradigme de
Perl est tr<74>s diff<66>rent de C++ en mati<74>re de copie d'objets.
=item Constantes
TQt n'utilise pas beaucoup de constantes, mais on en trouve cependant dans le module d'Entr<74>es/Sorties,
o<EFBFBD> elles font office de drapeaux pour les modes d'ouverture de fichiers.
Pour <20>viter de polluer inutilement l'espace de nom, nous avons regroup<75> les constantes dans le module
B<TQt::constants>, d'o<> elles seront charg<72>es <20> la demande.
Ainsi, pour importer l'ensemble des constantes d'E/S, on <20>crira :
use TQt::constants;
Et pour importer quelques symboles seulement :
use TQt::constants qw( IO_ReadOnly IO_WriteOnly );
=item Fonctions globales
TQt dispose de fonctions utilitaires, telles bitBlt, tqCompress, etc.
Ces fonctions ont <20>t<EFBFBD> rassembl<62>es dans un espace de nom commun:
C<TQt::GlobalSpace>.
Vous pourrez donc y acc<63>der soit par un appel pleinement qualifi<66> :
TQt::GlobalSpace::tqUncompress( $buffer )
Soit en important pr<70>alablement ces fonctions dans l'espace de nom courant :
use TQt::GlobalSpace;
tqUncompress( $buffer )
Bien entendu, vous pouvez aussi n'importer que les fonctions souhait<69>es :
use TQt::GlobalSpace qw( tqUncompress bitBlt )
B<N.B:> GlobalSpace renferme <20>galement des op<6F>rateurs de port<72>e globale, tels
celui permettant d'aditionner deux TQt::Point(). Ces op<6F>rateurs seront appel<65>s
automatiquement.
ex:
$p1 = TQt::Point(10, 10) + TQt::Point(20, 20)
=back
=head1 Annexe 2 : Internationalisation
PerlTQt r<>sout les probl<62>mes d'internationalisation en convertissant syst<73>matiquement les B<TQString>
de TQt en B<utf8> c<>t<EFBFBD> Perl.
Les conversions en sens inverse, depuis Perl vers TQt sont trait<69>es diff<66>remment suivant le contexte :
=over 4
=item * Si la cha<68>ne de caract<63>re est d<>j<EFBFBD> marqu<71>e comme <20>tant utf8
alors elle sera convertie en TQString directement.
C'est la mani<6E>re privil<69>gi<67>e d'op<6F>rer, et la plus simple :
Il vous suffit d'ins<6E>rer un pragma B<use utf8> en t<>te de vos programmes, puis d'utiliser un <20>diteur de
texte supportant l'utf8 (quasiment tous de nos jours) pour <20>laborer votre code source.
Les cha<68>nes seront marqu<71>es par Perl automatiquement.
=item * Si la cha<68>ne n'est pas marqu<71>e comme utf8, et le pragma 'use locale' n'est pas actif
alors la conversion en TQString se fera depuis l'B<ISO-Latin-1>.
=item * Si la cha<68>ne n'est pas marqu<71>e comme utf8, et le pragma 'use locale' est actif
alors la conversion en TQString se fera depuis votre B<locale>.
=back
Lorsque des cha<68>nes contiennent de l'utf8, Perl adapte automatiquement ses op<6F>rateurs pour que
leur gestion soit enti<74>rement transparente (comprendre opaque, comme toujours...).
Cependant, vous pourrez avoir besoin <20> l'occasion de les transcrire en d'autres jeux d'encodage.
Ceci peut se faire soit avec TQt :
$tr1=TQt::TextCodec::codecForLocale(); # ceci utilisera la locale en vigueur
$tr2=TQt::TextCodec::codecForName("KOI8-R"); # ceci force l'emploi d'une locale sp<73>cifique (Russe)
print $tr1->fromUnicode(TQt::DateTime::currentDateTime()->toString)."\n\n";
print $tr2->fromUnicode($une_chaine_utf8);
Soit avec les outils de Perl (pour perl >= 5.8.0).
Se reporter <20> ce sujet <20> la documentation du module B<Encode> (C<perldoc Encode>).
=head3 d<>sactiver l'encodage utf8
Les programmeurs souhaitant d<>sactiver temporairement l'encodage utf8
(pour la gestion de programmes externes ou de modules anciens ne supportant pas cet encodage)
pourront utiliser le pragma B<use bytes> (et sa r<>ciproque : B<no bytes>).
Dans la port<72>e de ce pragma, les conversions depuis TQString vers les cha<68>nes Perl se feront en ISO-Latin1
(par d<>faut) ou suivant la locale en vigueur (si B<use locale> est actif).
Notez bien qu'il est pr<70>f<EFBFBD>rable de I<ne pas utiliser ce pragma <20> la l<>g<EFBFBD>re>, en ce qu'il ruine totalement les
efforts de standardisations autour d'utf8 entrepris depuis plusieurs ann<6E>es d<>j<EFBFBD>.
Il est tr<74>s pr<70>f<EFBFBD>rable de corriger les programmes fautifs.
=head1 Annexe 3 : Canaux de d<>boguage
Le module B<TQt::debug> offre divers canaux de d<>boguage permettant de filtrer
le flux cons<6E>quent d'informations disponibles pour l'adapter <20> vos besoins.
use TQt::debug;
use TQt::debug qw|calls autoload verbose|;
Avec le pragma C<use TQt::debug>, seuls les canaux B<verbose> et B<ambiguous> sont activ<69>s.
Si vous le faites suivre d'une liste pr<70>cise de canaux, seuls ceux-ci seront affich<63>s.
B<Liste et descriptif des canaux :>
=over 4
=item * ambiguous
V<EFBFBD>rifier si les appels de m<>thodes sont ambigus, et dire quelle m<>thode, parmi le jeux
d'alternatives, <20> finalement <20>t<EFBFBD> choisie.
=item * verbose
Donner davantage d'informations.
Utilis<EFBFBD> avec B<ambiguous>, vous donnera les correspondances les plus proches lorsqu'un appel de m<>thode <20>choue.
ex:
use TQt;
use TQt::debug;
$a= TQt::Application(\@ARGV);
$a->libraryPath("chose");
--- No method to call for :
TQApplication::libraryPath('chose')
Closer candidates are :
static void TQApplication::addLibraryPath(const TQString&)
static TQStringList TQApplication::libraryPaths()
static void TQApplication::removeLibraryPath(const TQString&)
static void TQApplication::setLibraryPaths(const TQStringList&)
=item * calls
Pour chaque appel de m<>thode, vous dira quelle m<>thode TQt est finalement appel<65>e,
en pr<70>cisant les arguments si B<verbose> est actif.
=item * autoload
D<EFBFBD>taille le passage dans le code interm<72>diaire faisant la jonction entre Perl et TQt.
=item * gc
Donne des informations sur la collection des d<>chets, c'est <20> dire sur la destruction des objets,
qu'ils soient d<>truits depuis Perl ou TQt.
=item * virtual
Vous averti chaque fois qu'une fonction virtuelle tente d'acc<63>der <20> sa r<>impl<70>mentation en Perl
(que cette r<>impl<70>mentation existe ou non).
=item * all
Activer tous les canaux.
=back
=head1 Annexe 4 : Marshalleurs
Un marshalleur est un convertisseur permettant de transcrire un type de donn<6E>es en un autre.
Dans PerlTQt, la plupart des objets TQt gardent leurs propri<72>t<EFBFBD>s d'objet, ce qui permet d'invoquer leurs m<>thodes
et de changer leurs propri<72>t<EFBFBD>s comme il se doit.
Cependant, il arrive que l'objet d'origine corresponde <20> ce point <20> un type natif de Perl qu'il serait mals<6C>ant
d'utiliser l'interface C++ et beaucoup plus naturel de lui substituer son <20>quivalent.
Ici interviennent les marshalleurs.
Plut<EFBFBD>t que de retourner un objet TQt::StringList, qui serait d<>licat <20> manipuler,
PerlTQt le transformera en r<>f<EFBFBD>rence de liste Perl.
D<EFBFBD>s lors, tous les op<6F>rateurs de manipulation de liste pourront lui <20>tre appliqu<71> :
on gagne en densit<69>, en coh<6F>rence et en simplicit<69>.
Cette transformation s'appliquera aussi en sens inverse, et n'importe quelle liste de cha<68>nes Perl
pourra <20>tre donn<6E>e en argument <20> une m<>thode attendant une TQt::StringList.
Liste des marshalleurs (PerlTQt-3.008)
-----------------------------------------------------------------
float, double <=> r<>el Perl (NV)
char, uchar, int, uint, enum
long, ulong, short, ushort <=> entier Perl (IV)
TQString, -&, -* => cha<68>ne Perl (utf8)
TQString, -&, -* <= cha<68>ne Perl (utf8 ou iso-latin1 ou locale)
TQCString, -&, -* <=> cha<68>ne Perl (utf8 ou octets, suivant contenu ou pragma "bytes")
TQStringList, -&, -* => r<>f<EFBFBD>rence <20> une liste de cha<68>nes Perl (utf8)
TQByteArray, -&, -* <=> cha<68>ne Perl (octets)
int&, -* <=> entier Perl (IV)
bool&, -* <=> bool<6F>en Perl
char* <=> cha<68>ne Perl (octets)
char** <= r<>f<EFBFBD>rence <20> une liste de cha<68>nes Perl (octets)
uchar* <= cha<68>ne Perl(octets)
TQRgb* <= r<>f<EFBFBD>rence <20> une liste d'entiers Perl (IV)
TQCOORD* <= r<>f<EFBFBD>rence <20> une liste d'entiers Perl (IV)
void* <=> r<>f<EFBFBD>rence <20> un entier Perl (IV)
TQValueList<int>, - *, - & <=> r<>f<EFBFBD>rence <20> une liste d'entiers Perl (IV)
TQCanvasItemList, - *, - & => r<>ference <20> une liste de TQt::CanvasItem
TQWidgetList, - *, - & <=> r<>ference <20> une liste de TQt::Widget
TQObjectList, - *, - & <=> r<>ference <20> une liste de TQt::Object
TQFileInfoList, - *, - & <=> r<>ference <20> une liste de TQt::FileInfo
TQPtrList<TQTab>, - *, - & <=> r<>ference <20> une liste de TQt::Tab
TQPtrList<TQToolBar>, - *, - & <=> r<>ference <20> une liste de TQt::ToolBar
TQPtrList<TQNetworkOperation>, - *, - & <=> r<>ference <20> une liste de TQt::NetworkOperation
TQPtrList<TQDockWindow>, - *, - & <=> r<>ference <20> une liste de TQt::DockWindow
(TQUObject*)