![]() |
Programmation dans Anatomist: fabriquer un nouveau type de fenêtre |
![]() ![]() |
Regardez toujours la doc automatique en meme temps... (et les sources
des classes que je donne en exemple, ça peut aider
aussi)
Les fenêtres dérivent de la classe de base AWindow, qui
elle-même est un observateur (une fenêtre observe les objets
qui sont affichés dedans).
On va prendre l'exemple d'une nouvelle fenêtre: ABubu.
Le ménage n'ayant pas encore été fait dans les
classes de fenêtres, il y a encore pas mal de fonctions virtuelles
pures et de choses à redéfinir. C'est un peu plus complexe
que pour les objets qui ont été un tout petit peu nettoyés.
Il n'y a pas non plus d'exemple très simple de fenêtre
dans la librairie anatomist, regardez quand-même QObjectBrowser,
c'est la plus récente et donc la plus propre (et aussi, elle ne
fait pas de visu donc ça simplifie la présenration de la
partie générique sans visu).
Je n'ai mis ici que les fonctions virtuelles pures à redéfinir obligatoirement, mais il y en a plein d'autres dont la redéfinition est plus que fortement conseillée. En fait un grand nombre de ces fonctions à redéfinir vient du fait que l'interface est indépendante de la librairie graphique utilisée (Motif/MPP ou Qt) et qu'il faut surcharger en fonction (resizes, géométrie, iconification, titre de la fenêtre etc). Pour bien faire, il faudrait interposer une seconde couche Motif ou Qt (AQtWindow et AMotifWindow par ex.). C'est un peu ce qui est fait du côté Motif/Mpp (AMainWindow / AMenuWindow), et que j'ai pas fait du côté Qt (mea culpa).class ABubu : public AWindow {public:ABubu( params quelconques... ); virtual ~ABubu(); static AWindow* createBubu(); virtual Type type() const;virtual Point3df GetPosition() const; virtual void SetPosition( const Point3df& position , const Referential *refdep ); virtual void SetTime( float time ); virtual void DisplayClickPoint();virtual void setGeometry( int x, int y, unsigned w, unsigned h ); virtual void geometry( int *x, int *y, unsigned *w, unsigned *h ); virtual void CreatePixMap(); // celle-là devrait disparaître, je ne vois pas ce qu'elle fout ici...virtual void Refresh();protected:virtual void CreateTitle(); virtual void Draw( bool flush = true );private:static int registerClass();static set<unsigned> _bubuCount; static string _baseTitle; static int _classType;};
setGeometry() positionne et dimentionne la fenêtre sur
l'écran (QWidget::setGeometry() en Qt)
geometry()au contraire, retourne la position et les dimentions
de la fenêtre
show()affiche et désiconifie la fenêtre. Il faut
toujours rappeler la fonction AWindow::show(). En Qt:
Unmanage() iconifie la fenêtre. Pareil que pour Manage(). En Qt:void ABubu::show() { QWidget::show(); AWindow::show(); }
SetTitle() met la ligne de titre de la fenêtre (window manager). Il faut aussi appeler AWindow::SetTitle() avant. En Qt:void ABubu::hide() { AWindow::hide(); QWidget::hide(); }
void ABubu::SetTitle( const string title ) { AWindow::SetTitle( title ); setCaption( title.c_str() ); }
createBubu() est la fonction qui est appelée par l'usine à fenêtres et qui crée une fenêtre à partir de l'interface graphique (bouton):string ABubu::_baseTitle = "Bubu"; // titre de base pour les fenêtres de ce type int ABubu::_classType = registerClass();int ABubu::registerClass() { int type = AWindowFactory::registerType( _baseTitle, createBubu ); return( type ); }
Nouveau (01/10/00): maintenant on peut aussi stocker les pixmaps et des descriptifs dans une extension de l'usine à fenêtres: QAWindowFactory. Les pixmaps en 3 versions (small, large, active) sont stockés ici. Ils sont chargés automatiquement à la création de la fenêtre de contrôle -rien besoin de faire !- s'ils sont stockés à l'emplacement standard avec des noms standards: dependencies/icons/window-type-small.xpm, dependencies/icons/window-type-large.xpm, dependencies/icons/window-type-active.xpm.AWindow* QABubu::createBubu() { ABubu* b = new ABubu( params... ); b->Manage(); return( b ); }
La description brève est mise par défaut ("Fenêtre de type Bubu") si on ne met rien.QAWindowFactory::setDescription( "Bubu", QAWindowFactoty::Descrip( "description brève", "c'est une nouvelle fenêtre. Elle s'appelle Bubu. " "C'est un joli nom, non ?" ) );
void ABubu::CreateTitle() { if( _instNumber >= 0 ) return; // already done set<unsigned>::iterator si; unsigned n; char nstr[20]; for( si=_bubuCount.begin(), n=0; si!=_bubuCount.end() && *si==n; ++si, ++n ); _instNumber = n; _bubuCount.insert( n ); sprintf( nstr, "%d", n+1 ); if( n == 0 ) SetTitle( _baseTitle ); else SetTitle( _baseTitle + " (" + nstr + ")" ); }
Le destructeur doit retirer le numéro de la fenêtre dans la liste statique des numéros utilisés:ABubu::ABubu() : AWindow() { }
N.B: Heu, n'oublions pas qu'en Qt, quand on ferme une fenêtre, par défaut elle n'est pas détruite. Pour que ce soit le cas, ne pas oublier de passer le flag WDestructiveClose au constructeur de QWidget.ABubu::~ABubu { if( _instNumber != -1 ) _bubuCount.erase( _bubuCount.find( _instNumber ) ); }