Is this page loading slow? Try the mirror site!

Manuel Kiessling's Personal Home Page

Navigate:      Previous | Next | Home | Sitemap | News | Personal | Projects | Topics | Download | External Links | About this page

PHP-Gtk Tutorial

Walkthrough des Listings, Teil 2

Mit Gtk Objekten verknüpfte Funktionen sind ganz 'normale' PHP Funktionen. Hier zum Beispiel die nicht wirklich aufregende Funktion, die wir vorhin mit dem delete Event des Hauptfensters verbunden haben:

// Functions connected to Gtk objects ///

function delete_event()
{
 return false;
}

Ok, kommen wir zu einer etwas anspruchsvolleren Funktion, nämlich der, die wir mit dem Button Loeschen verbunden haben und die nach drücken des Buttons die aktuell ausgewählte Nachricht aus der Datenbank entfernen soll:

function loesche_eintrag()
{
 GLOBAL $list;
 GLOBAL $verschiebung;
 $row = $list->selection[0];
 $id = $list->get_text($row, 0);

 $result = mysql_query("DELETE from nachrichten WHERE id = '$id'");

 lade_day($verschiebung);

 return false;
}

Um den richtigen Eintrag zu löschen, brauchen wir die ID der aktuell in der Liste ausgewählten Nachricht. Die ID steht jeweils in der ersten Spalte der Liste und kann von dort ausgelesen werden. Um in dieser Funktion darauf zugreifen zu können, müssen wir unsere Liste der Funktion durch GLOBAL erst bekanntmachen, ausserdem globalisieren wir auch noch die Variable $verschiebung - was es damit auf sich hat wird später klar. Ersteinmal finden wir heraus, welche Zeile in der Liste momentan ausgewählt ist, indem wir den ersten Wert des Arrays selection des Objekts $list auslesen. selection ist deshalb ein Array, weil bei einigen Listentypen auch mehrere Zeilen gleichzeitig ausgewählt sein können und die Nummern der ausgewählten Zeilen in diesem Array gespeichert werden. Da in unserer Liste immer nur eine Zeile gleichzeitig ausgewählt sein kann, muss der Wert an Position 0 im Array gespeichert sein. Den Wert der ID bekommen wir nun, indem wir die Funktion get_text unter Angabe der Reihe (die wir eben erfahren haben) und der Spalte (da es sich um die erste Spalte handelt hier 0) aufrufen - somit bekommen wir den Inhalt der durch dieses Koordinatenpaar definierten Zelle zurückgeliefert, eben unsere ID. Damit können wir dann den entsprechenden MySQL Aufruf ausführen, um diesen Eintrag zu löschen.
Damit unsere Liste jetzt den gelöschten Eintrag nicht mehr anzeigt, müssen die Einträge der Datenbank neu eingelesen werden, dass erledigt der lade_day Aufruf - dazu später wie gesagt mehr.

Schreiben wir jetzt eine Funktion die den Fall abfängt, dass eine Zeile in der Liste ausgewählt wird:

function list_change()
{
 GLOBAL $list;
 GLOBAL $label;
 $row = $list->selection[0];
 $id = $list->get_text($row, 0);

 $result = mysql_query("SELECT text, datum, zeit, rubrik
                        from nachrichten WHERE id = '$id'");
 $a = mysql_fetch_array($result);
 $string = $a["text"];

 $string = sonderzeichen($string);

 GLOBAL $text;
 $length = $text->get_length();
 $text->backward_delete($length);
 $text->freeze();
 $text->insert(NULL, NULL, NULL, $string, -1);
 $text->thaw();
 $length = $text->get_length();
 $label->set_text("ID $id, Laenge $length, Datum ".$a["datum"].", ".
                   $a["zeit"]." Uhr, Rubrik ".$a["rubrik"]);

 return false;
}

Zuerst wieder das selbe Spiel wie eben: Die Elemente der Benutzeroberfläche, die wir verändern oder auslesen wollen, müssen der Funktion durch GLOBAL bekannt gemacht werden - in diesem Fall die Liste, das Label und das Textfeld (weiter unten). Dann holen wir uns genau wie eben die ID der aktuell ausgewählten Nachricht mit $list->selection und $list->get_text. Diese ID brauchen wir dann, um einige Werte aus der Datenbank auszulesen: den Nachrichtentext, das Datum der Nachricht, die Zeit und die Rubrik. Damit wie eingangs erwähnt Gtk keine Probleme mit Umlauten macht, filtern wir den Text der Nachricht durch unsere sonderzeichen Funktion.
Zunächst wollen wir den Text der Nachricht im grossen Textfenster anzeigen lassen. Da ja unter Umständen schon ein Text dort angezeigt wird, müssen wir das Nachrichtenfeld ersteinmal löschen. Das geht leider nicht mit einem einzigen Befehl. Wir müssen erst die Anzahl Zeichen auslesen, die momentan im Feld geladen sind (über den Befehl get_length), und dann mit dem Befehl backward_delete genau diese Anzahl Zeichen von der aktuellen Position im Text rückwärts löschen. Da unser Textfeld nicht editierbar ist, kann die aktuelle Position im Text (die Position eines sozusagen imaginären Zeigers, der, wenn das Textfeld editierbar wäre, gar nicht mehr so imaginär, sondern eher schwarz, senkrecht und blickend wäre) immer nur am Ende liegen. Wir löschen also auf jeden Fall alle Zeichen.
Jetzt werden wir den neuen Text in das Feld laden. Bevor wir das tun, werden wir das Textfeld 'einfrieren'. Das ist nicht unbedingt erforderlich, auf jeden Fall aber sauberer: Wenn ein Element eingefroren ist, werden Änderungen erst wieder sichtbar, wenn es mittels thaw() wieder freigegeben wird. Das ist sinnvoll wenn mehrere komplexe Änderungen an einem Element vorgenommen werden, damit der User kein 'flackern' des Elements bei jeder Änderungen sieht. Das einfrieren eines Elements geschieht mittels Aufruf der Funktion freeze. Nicht jedes Element kann eingefroren werden.
Um dann den neuen Nachrichtentext (gespeichert in $string) in das Feld einzufügen benutzt man die Funktion insert. insert erwartet 5 Parameter: den zu verwendenden Font, die Schriftfarbe, die Hintergrundfarbe der Schrift, den Textstring und die Anzahl der Zeichen die vom Textstring verwendet werden sollen. Font und Schriftfarben interessieren hier ersteinmal nicht, deshalb setzen wir diese Parameter alle auf NULL. Wir übergeben als vierten Parameter den Text der Nachricht, bei der Anzahl der Zeichen übergeben wir einfach -1, damit der komplette String übernommen wird. Nachdem das Textfeld gefüllt wurde können wir es jetzt mittels $text->thaw() wieder freigeben.
Jetzt muss noch das Labelfeld geupdated werden. Zuerst holen wir uns noch die Anzahl der momentan im Textfeld geladenen Zeichen mittels get_length(), dann benutzen wir die Funktion set_text des Labelobjekts, um unseren neuen Informationsstring (der den alten ersetzt) in das Label zu schreiben.
Wir schliessen die Funktion wie schon zuvor mit return false ab.

Kommen wir jetzt zu der Funktion, die unsere Liste mit den IDs, Überschriften und Rubriken der Nachrichten des gewählten Tages füllt:

function lade_day($verschiebung)
{
 GLOBAL $list;
 $tag = date("Y-m-d", mktime(0, 0, 0, date("m"),
                             date("d") + $verschiebung,
                             date("Y")));
 $list->clear();
 $list->freeze();
 $result = mysql_query("SELECT id, ueberschrift, rubrik from nachrichten
                        WHERE datum = '$tag'");
 while ($a = mysql_fetch_array($result))
 {
  $a["ueberschrift"] = sonderzeichen($a["ueberschrift"]);
  $thisarray = array($a["id"], $a["ueberschrift"], $a["rubrik"]);
  $list->append($thisarray);
 }
 $list->thaw();
 return false;
}

Da wir die Liste verändern müssen, machen wir sie mittels GLOBAL unserer Funktion bekannt. Dann finden wir das Datum heraus, dass wir uns anzeigen lassen wollen, ausgehend vom heutigen Datum abzüglich oder zuzüglich der $verschiebung (welche mittels der Buttons Einen Tag zurueck, Einen Tag vor, Eine Woche zurueck und Eine Woche vor eingestellt wird). Wir löschen die Liste und frieren sie ein, dann holen wir aus der Datenbank die Datensätze des berechneten Tages.
Wir arbeiten dann die Datensätze mittels mysql_fetch_array Zeile für Zeile durch. In der Schleife ersetzen wir in der Überschrift sicherheitshalber die Sonderzeichen, dann erzeugen wir ein Array aus drei Elementen (ID, Überschrift, Rubrik) und hängen dieses Array mittels append an die Liste an. Nachdem die Liste auf diese Weise gefüllt wurde, geben wir sie via thaw wieder frei.
Jetzt fehlen nur noch unsere restlichen Buttons. Ein Klick auf einen der Buttons Einen Tag zurueck, Einen Tag vor, Eine Woche zurueck oder Eine Woche vor muss nur die $verschiebung des Datums um 1 bzw. 7 erhöhen bzw. vermindern und die Funktion lade_day aufrufen, damit die aktuellen Datensätze in die Liste geschrieben werden:

function lade_prevday()
{
 GLOBAL $verschiebung;
 $verschiebung--;
 lade_day($verschiebung);
 return false;
}

function lade_nextday()
{
 GLOBAL $verschiebung;
 $verschiebung++;
 lade_day($verschiebung);
 return false;
}

function lade_prevweek()
{
 GLOBAL $verschiebung;
 $verschiebung = $verschiebung - 7;
 lade_day($verschiebung);
 return false;
}

function lade_nextweek()
{
 GLOBAL $verschiebung;
 $verschiebung = $verschiebung + 7;
 lade_day($verschiebung);
 return false;
}

Mit dem Aufruf

# /usr/local/bin/php -q /pfad/zum/gpnma-skript.php

unter X wird das Skript gestartet.

Ich habe das Skript nach bestem Wissen und Gewissen gestestet - sollte sich dennoch irgendwo der Fehlerteufel eingeschlichen haben, würde ich mich über eine entsprechende eMail freuen. Auch Lob und Kritik sind willkommen, und ich bin gerne bereit auch weiterführende Fragen zu beantworten - allerdings entdecke ich PHP-Gtk auch gerade erst und kann nicht versprechen, jede Frage beantworten zu können. Der eMail Link steht im Fuss dieser Seite.

Previous | Next

Last updated: $Date: 2001/07/16 00:16:14 $ by MK

Everything on this page is copyleft 2001 Manuel Kiessling unless otherwise stated. You may use it after you read the About section.