/* Datei hello.cc Ein "Hello World"-Programm für Gtk--, das die Widgets mit Hilfe von manage() verwaltet. Dieses Programm definiert zunächst eine von Gtk::Window abgelei- tete Klasse HelloWindow, die zwei Buttons und ein Label in der folgenden Weise in einem Fenster anordnet: +--------+-------+ | Button | Label | +--------+-------+ (Zur Festlegung der Anordnung werden | Button | eine HBox und eine VBox verwendet) +----------------+ In main() wird eine Instanz dieser Klasse erzeugt und benutzt. */ #include // Headerfile für Gtk::Window, ein Hauptfenster für X11-Anwendungen: #include /* Für die Deklaration der neuen Klasse, die normalerweise in einem Headerfile stehen würde, müssen wir jetzt, wo mit manage() gearbeitet wird, nur die Headerdatei der Klasse einlesen, von der unsere neue Klasse erbt. Die auftretenden Widgets müssen auch nicht vorher mit namespace Gtk {class Name;} deklariert werden. Das führt dazu, dass sich die Headerdatei bei einer Änderung der Implementierung (z.B. CheckButton statt ToggleButton verwenden) nicht zwangsläufig mit ändern muss. Bei großen Projekten kann das zu erheblich weniger Aufwand bei der Neuübersetzung nach einer solchen Änderung führen, weil nicht mehr alle Quelldateien, die diese Headerdatei einlesen, neu übersetzt werden müssen. Mit manage() reduziert man also die Abhängigkeiten der Quelldateien untereinander. */ // Die neue Klasse, die von einem leeren Anwendungsfenster erbt: class HelloWindow : public Gtk::Window { // ... keine eigenen Attribute! protected: // Wir überschreiben eine virtuelle Funktion, die automatisch // aufgerufen wird, wenn das Anwendungsfenster durch den Window- // manager geschlossen werden soll: virtual gint delete_event_impl(GdkEventAny*); public: // Der Konstruktor erhält drei Strings als Argumente, die von // den Buttons (1. und 3. String) bzw. dem Label angezeigt werden. HelloWindow(const string & hello_string, const string & world_string, const string & bye_string); // Callback-Methode, die aufgerufen werden soll, wenn auf den // oberen linken Button geklickt wird. void say_hello(void); // Gibt "Hello!" auf dem Terminal aus. // Callback-Methode, die aufgerufen werden soll, wenn auf den // unteren Button geklickt wird. void say_goodbye(void); // Gibt "Good Bye" aus und beendet das Programm. }; // Zur Implementierung der Klasse müssen jetzt die Header-Dateien der // verwendeten Widgets eingelesen werden: // Headerfile für Gtk::HBox, Gtk::VBox, zwei Container, die // beliebige Widgets neben- bzw. übereinander anordnen: #include #include // Gtk::Label #include // Gtk::Button // Headerfile für Gtk::Main. Jede Gtk-- Anwendung muss genau ein // Objekt dieses Typs instanzieren. #include HelloWindow::HelloWindow(const string & hello_string, const string & world_string, const string & bye_string) { // Zeiger auf einige Objekte müssen temporär im Konstruktor // referenziert werden: Gtk::HBox * hbox; Gtk::Button * hello_button; // der Button oben links Gtk::VBox * vbox; Gtk::Button * bye_button; // der untere Button // Die Boxen erzeugen: hbox = manage(new Gtk::HBox); vbox = manage(new Gtk::VBox); // Den oberen linken Button erzeugen und in die HBox einfügen: hello_button = manage(new Gtk::Button(hello_string)); hbox->add(*hello_button); // Das obere rechte Label erzeugen und in die HBox neben den Button einfügen: hbox->add(*manage(new Gtk::Label(world_string))); // Die HBox in die VBox einfügen: vbox->add(*hbox); // Den unteren Button erzeugen und unter die HBox einfügen, // die den anderen Button und das Label enthält: bye_button = manage(new Gtk::Button(bye_string)); vbox->add(*bye_button); // Die VBox in das Anwendungsfenster (*this) einfügen: add(*vbox); // Die VBox und alle darin enthaltenen Widgets anzeigen: vbox->show_all(); // Buttons mit den Callbacks verbinden (s. Kasten über libsigc++): hello_button->clicked.connect(SigC::slot(this, &HelloWindow::say_hello)); bye_button->clicked.connect(SigC::slot(this, &HelloWindow::say_goodbye)); } // Außerhalb des Konstruktors ist keine Änderung notwendig, weil auf die // enthaltenen Widgets nie mehr zugegriffen wird: // (Wäre das nicht so, müßte die Klasse doch ein entsprechendes Attribut // enthalten.) void HelloWindow::say_hello(void) { cout << "Hello!" << endl; } void HelloWindow::say_goodbye(void) { cout << "Good bye!" << endl; Gtk::Main::quit(); // Exit event loop } // Das Fenster soll vom Windowmanager geschlossen werden: gint HelloWindow::delete_event_impl(GdkEventAny*) { Gtk::Main::quit(); // Exit event loop // Rückgabewert true verhindert, dass das Fenster sofort nach // der Rückkehr zerstört wird. // (In diesem Fall wäre das eigentlich egal, weil // das Programm sowieso anschließend beendet wird.) return true; } // Benutzt wird die Klasse genauso wie vorher: int main(int argc, char ** argv) { // Eine Instanz von Main wird erzeugt. Sie durchsucht die // Kommandozeilenelemente und entfernt diejenigen, die vom // Toolkit bearbeitet werden. Gtk::Main kit(argc, argv); // Eine Instanz des Anwendungsfensters erzeugen und anzeigen. HelloWindow hello("Hello,", "World!", "Good" "\n" "bye!"); hello.show(); // Eventschleife. Aus dieser Funktion heraus werden die Callbacks // aufgerufen. kit.run(); return 0; }