Éléments graphiques

XXV.I.I. Gestion classique de la mémoire en C++

gtkmm autorise le programmeur à contrôler la durée de vie (c'est-à-dire, la construction et la destruction) de tout élément graphique de la même manière que celle de n'importe quel objet C++. Cette polyvalence autorise, soit l'utilisation des opérateurs new et delete pour créer et détruire les objets de manière dynamique, soit l'utilisation de données membres de classes régulières (qui sont détruites automatiquement quand la classe est détruite), soit l'utilisation d'instances locales (qui sont détruites dès que l'instance est hors de portée). Certaines boîtes à outils GUI C++ n'offrent pas cette souplesse : elles restreignent le programmeur à un sous-ensemble des fonctionnalités de gestion mémoire du C++.

Voici quelques exemples de gestion traditionnelle de la mémoire en C++ :

XXV.I.I.I. Éléments graphiques à portée de classe

Si un programmeur n'a pas besoin d'allocation dynamique de mémoire, il peut se servir d'éléments graphiques automatiques à portée de classe. Un des avantages des éléments graphiques automatiques à portée de classe est que la gestion de la mémoire est regroupée en un seul endroit. Le programmeur ne risque pas de fuites de mémoire en oubliant un delete sur un élément graphique.

The primary disadvantage of using class scope widgets is revealing the class implementation rather than the class interface in the class header.

#include <gtkmm/button.h>
#include <gtkmm/window.h>
class Foo : public Gtk::Window
{
private:
  Gtk::Button theButton;
  // will be destroyed when the Foo object is destroyed
};

XXV.I.I.II. Éléments graphiques à portée de fonction

Si un programmeur ne souhaite pas utiliser d'élément graphique à portée de classe, il peut aussi se servir d'éléments graphiques à portée de fonction. Les avantages de la portée de fonction par rapport à la portée de classe sont un masquage accru des données et une réduction des dépendances.

{
  Gtk::Button aButton;
  aButton.show();
  ...
  app->run();
}

XXV.I.I.III. Allocation dynamique avec new et delete

Although, in most cases, the programmer will prefer to allow containers to automatically destroy their children using Gtk::manage() (see below), the programmer is not required to use Gtk::manage(). The traditional new and delete operators may also be used.

Gtk::Button* pButton = new Gtk::Button("Test");

// faire quelque chose d'utile avec pButton

delete pButton;
Here, the programmer deletes pButton to prevent a memory leak.

XXV.I.II. Éléments graphiques gérés

Alternatively, you can let a widget's container control when the widget is destroyed. In most cases, you want a widget to last only as long as the container it is in. To delegate the management of a widget's lifetime to its container, first create it with Gtk::manage() and pack it into its container with Gtk::Container::add(), Gtk::Box::pack_start(), or a similar method. Now the widget will be destroyed whenever its container is destroyed.

XXV.I.II.I. Allocation dynamique avec manage() et add()

gtkmm provides the manage() function and add() methods to create and destroy widgets. Every widget except a top-level window must be added or packed into a container in order to be displayed. The manage() function marks a widget so that when the widget is added to a container, the container becomes responsible for deleting the widget.

MyContainer::MyContainer()
{
  Gtk::Button* pButton = Gtk::manage(new Gtk::Button("Test"));
  add(*pButton); //add *pButton to MyContainer
}
Now, when objects of type MyContainer are destroyed, the button will also be deleted. It is no longer necessary to delete pButton to free the button's memory; its deletion has been delegated to the MyContainer object.

Of course, a top-level container will not be added to another container. The programmer is responsible for destroying the top-level container using one of the traditional C++ techniques. For instance, your top-level Window might just be an instance in your main() function.