Conheça o Adianti Framework para PHP:

  • Desenvolvimento com componentes;
  • Formulários e datagrids.
  • Versão Web e Desktop (Gtk);
  • Multiplataforma;
  • Desenhe as interfaces;
  • IDE própria (Adianti Studio).
Ver detalhes...

New features of PHP-GTK2

Para prosseguir com o download do artigo, é necessário realizar login utilizando o Facebook ou Google. Este procedimento é totalmente seguro e nossa aplicação é certificada por ambos os serviços. Após a autenticação, você será direcionado de volta à nossa página para continuar o download.

Login com Facebook Login com Google

Resumo

by Pablo Dall'Oglio Summary PHP-GTK1 started a new way of thinking of PHP. The language that was used mainly for web applications started to be widely used for graphic standalone applications. With this article we'll cover the new aspects of the PHP-GTK2, the new version of this the partnership between PHP and GTK. Introduction The first "generation" of PHP-GTK was a language binding beween PHP-4.x and Gtk-1.2. This version, that is still used by the majority of projects, was hindered by PHP4's object model. As soon as PHP5 was launched, The PHP-GTK creator's Andrei Zmievski, started a hard task to rewrite the code base of PHP-GTK to use the new facilities of PHP5 and Gtk2, the main part of the work was to take advantage of the new PHP's object model and Gtk2's new features, that involves the new flexible type system (as PHP) and a good extensibility, what makes easier the task of mapping Gtk2 API onto PHP's object model. PHP-GTK2, is a binding between PHP-5.1 and Gtk-2.6 library. In this article, we'll have an overview on some topics about this platform that promises to be an great combination that will allow people to write complex and object oriented standalone applications with the flexibility of their favorite language, PHP, with the beauty and power of Gtk library. Instead of showing feature by feature, we'll write a real application centered on an interface, explainning these features through real world programs. It's important highlight that PHP-GTK2 is a work in progress that is on an alpha stage. The installation instructions for both linux and windows you'll find at the official site (http://gtk.php.net). The Main interface In order to show the new features of PHP-GTK2, we'll build a very simple interface to deal with a products database. This interface will consist of a window with a menu bar with some basic options. Options from menu File The "Clear" option starts the database, drop the products table and creates it again. The "Add" options show a products' form to the end user insert a new product. The "Edit" option show the products listing to the end user allowing him to edit its records. The "Quit" option exits the application. Options from menu File The "Edit" option starts the embedded text editor. Options from menu Help The "Help" option starts the AboutDialog Window. Stock Images When developing applications, it's very usual to need images like (save, open, close, delete, add, clear, quit, yes, no, among others...). Almost everytime we need this. In order standardize the look of applications, Gtk2 offer us the stock images, a set of common images to use in our application for buttons, menus, listings and others. Using stock images, we don't need to worry about what icon to use for some operation. You'll see stock images in all menu itens used in the main interface. Message Dialogs PHP-GTK2 offer us a flexible Dialog Box (GtkMessageDialog) that can be used in many situations (warning messages, error messages, confirmation dialogs, input boxes and so on). We can also use a set of stock buttons with their respective responses for dialogs. Here, you'll see Message Dialogs used when the user wants to restart the database (onClear Method) in order to ask him whether the application must really clear the database or not, and showing him a success dialog at the end of the operation. All Interface is set by the __construct() method, that builds the main window, the menu bar and the menu items, besides connect the menu items with their respective callbacks. The onClear() method is all built in this code. The onAdd(), onList(), onEdit() and onHelp() methods use another classes to perform their operations. These another classes we'll explain ahead. This is the code of the Main Interface. Product.php window = new GtkWindow;         $this->window->set_size_request(400,200);         $this->window->set_uposition(100,100);         $this->window->set_title('My Products');                  $vbox = new GtkVBox;         // creates the menubar         $MenuBar = new GtkMenuBar;                  // menu options         $MenuFile = new GtkMenuItem('_File');         $MenuEdit = new GtkMenuItem('_Edit');         $MenuHelp = new GtkMenuItem('_Help');                  // sub-menu File with stock-itens         $SubMenuFile = new GtkMenu;         $ItemFile1= new GtkImageMenuItem(GTK::STOCK_CLEAR);         $ItemFile2= new GtkImageMenuItem(GTK::STOCK_ADD);         $ItemFile3= new GtkImageMenuItem(GTK::STOCK_EDIT);         $ItemFile4= new GtkMenuItem;         $ItemFile5= new GtkImageMenuItem(GTK::STOCK_QUIT);                  // connect menu options to the methods         $ItemFile1->connect('activate', array($this, 'onClear'));         $ItemFile2->connect('activate', array($this, 'onAdd'));         $ItemFile3->connect('activate', array($this, 'onList'));         $ItemFile5->connect('activate', array($this, 'onQuit'));         // append the items to the sub-menu         $SubMenuFile->append($ItemFile1);         $SubMenuFile->append($ItemFile2);         $SubMenuFile->append($ItemFile3);         $SubMenuFile->append($ItemFile4);         $SubMenuFile->append($ItemFile5);                  // sub-menu edit         $SubMenuEdit= new GtkMenu;         $ItemEdit1= new GtkImageMenuItem(GTK::STOCK_EDIT);         $ItemEdit1->connect('activate', array($this, 'onEdit'));         $SubMenuEdit->append($ItemEdit1);                  // sub-menu help         $SubMenuHelp= new GtkMenu;         $ItemHelp1= new GtkImageMenuItem(GTK::STOCK_HELP);         $ItemHelp1->connect('activate', array($this, 'onHelp'));         $SubMenuHelp->append($ItemHelp1);                  $MenuFile->set_submenu($SubMenuFile);         $MenuEdit->set_submenu($SubMenuEdit);         $MenuHelp->set_submenu($SubMenuHelp);                  $MenuBar->append($MenuFile);         $MenuBar->append($MenuEdit);         $MenuBar->append($MenuHelp);                  $this->window->add($vbox);         $vbox->pack_start($MenuBar, false, false);                  $this->window->show_all();     }          /**      * Method onClear      * Creates the database structure      */     function onClear()     {         // check if the DB is already created         if (file_exists('data.db'))         {             // ask if the user want to clear             $dialog = new GtkMessageDialog(null, Gtk::DIALOG_MODAL, Gtk::MESSAGE_QUESTION,                                                  Gtk::BUTTONS_YES_NO,                                                 'Do you want to restart the database ?');                          $response = $dialog->run();             $dialog->destroy();                          // Tests the response             if ($response == Gtk::RESPONSE_YES)             {                 // drop the table products                 $conn = sqlite_open('data.db');                 $sql = 'DROP TABLE products';                 sqlite_query($conn, $sql);             }             else if ($response == Gtk::RESPONSE_NO)             {                 return;             }                      }                  // create the table products         $conn = sqlite_open('data.db');         $sql = 'CREATE TABLE products (code, description, ' .                '  unit, amount, cost, price)';         sqlite_query($conn, $sql);                  // show the success message to the user         $dialog = new GtkMessageDialog(null, Gtk::DIALOG_MODAL, Gtk::MESSAGE_INFO,                                        Gtk::BUTTONS_OK, 'Database clear');                  $response = $dialog->run();         $dialog->destroy();     }     /**      * Method onAdd      * Creates the Products Form      */     function onAdd()     {         include_once 'ProductNew.class.php';         new ProductNew;     }     /**      * Method onList      * Show the Products Listing      * allowing the user to change the data      */     function onList()     {         include_once 'ProductList.class.php';         $obj = new ProductList;         $obj->Show();         $obj->showData();     }     /**      * Method onEdit      * Opens a little Text Editor      */     function onEdit()     {         include_once 'TextEditor.class.php';         new TextEditor;     }     /**      * Method onHelp      * Show the About Dialog      */     function onHelp()     {         include_once 'AboutDialog.class.php';         new AboutDialog('Products', 'This software is open-source');     }     /**      * Method onQuit      * Quit the Application      */     function onQuit()     {         Gtk::main_quit();     } } // creates a new instance of Application new Application; Gtk::Main(); ?> The Products Form In order to show features like markup language for text effects, the new GtkExpander and the GtkEntryCompletion component, we'll produce a little form to allow the end user to enter with new products. Completion Entry with Auto-Completion is another special feature added by Gtk2. It allows to link a GtkEntry widget with a GtkListStore, a data model with possible values to be used for auto-completion while the user types. It's very common in Gtk applications, specially for File Dialogs to suggest the files that matches with the typed value. In our sample, we'll use EntryCompletion in the "Unit" field to list a set of common used units. Text Effects In PHP-GTK1 was a bit pain to format text to show on the screen. Simple things like Bold, Italic, Underline and colors needed a good patience to realize how it worked. Now PHP-GTK2 uses Pango, a GTK open-source framework that deals with all layout and rendering stuffs. With Pango it's possible to use a markup language derived from SGML to format text for exhibition, a simple way to define style and colors. Despite it's not shown here, it's possible to write text vertically or using angles (expressed in degrees). It's specially cool to decorate applications in different situations. In our little sample, we'll use colors to indicate what fields are really necessary to be filled. Expander GtkExpander is an interesting component added by Gtk2. It's a container with a label that has a little button to expand or collapse its content. It's specially usefull for applications with optional data to fill. It's used in Gaim (the instant messaging) to show/hide optional parameters like host, port, encoding and proxy type of an account. In our sample, we'll provide a little help at the bottom of the form that can be shown/hidden through an Expander. All the interface is set by __construct() method. Here, you'll see features like labels with the new markup language, GtkExpander (used by the help above the form) and GtkCompletion used by the units field to help the end user type values. When the user clicks on the "Save" Button, the method onSaveClick() is called, storing the values on the database and clearing the form through the Clear() method. This is the code of the Products Form ProductNew.class.php labels  = array();         $this->entries = array();         // creates all the labels and entries, line by line         $this->labels[0]  = new GtkLabel(' Code ');         $this->entries[0] = new GtkEntry;         $this->entries[0]->set_size_request(80,-1);                  $this->labels[1]  = new GtkLabel(' Description ');         $this->entries[1] = new GtkEntry;         $this->entries[1]->set_size_request(240,-1);                  $this->labels[2]  = new GtkLabel('Amount');         $this->entries[2] = new GtkEntry;         $this->entries[2]->set_size_request(240,-1);                  $this->labels[3]   = new GtkLabel('Unit');         $this->entries[3]  = new GtkEntry;         $this->entries[3]->set_size_request(48,-1);                  # Creates the DataModel         $store = new GtkListStore(Gtk::TYPE_STRING);                  # Append values to the DataModel         $store->append(array('UN'));         $store->append(array('PC'));         $store->append(array('OZ'));         $store->append(array('KG'));         $store->append(array('LT'));                  # Creates the EntryCompletion         $completion = new GtkEntryCompletion();         $completion->set_model($store);         $completion->set_text_column(0);         $this->entries[3]->set_completion($completion);                  $this->labels[4]   = new GtkLabel('Cost');         $this->entries[4]  = new GtkEntry;         $this->entries[4]->set_size_request(140,-1);                  $this->labels[5]   = new GtkLabel(' Price ');         $this->entries[5]  = new GtkEntry;         $this->entries[5]->set_size_request(240,-1);         // pack all the labels and entries to the vertical box         for ($n=0; $n<=5; $n++)         {             $hbox = new GtkHBox;             $this->labels[$n]->set_size_request(200,-1);                          $this->labels[$n]->set_use_markup(true);             $this->labels[$n]->set_alignment(0.5, 0.5);                          $hbox->pack_start($this->labels[$n], false, false);             $hbox->pack_start($this->entries[$n], false, false);                          $vbox->pack_start($hbox, false, false);         }                  // create the save button box         $save_box= new GtkHBox();         $button1  = GtkButton::new_from_stock(Gtk::STOCK_SAVE);         $button1->connect('clicked', array($this, 'onSaveClick'));                  $save_box->pack_start(new GtkHBox, true);         $save_box->pack_start($button1, false, false);         $save_box->pack_start(new GtkHBox, true);                  $vbox->pack_start($save_box, false, false);                  $separator = new GtkHSeparator();         $vbox->pack_start($separator, false, false);                  // Create an expander         $expander = new GtkExpander('Help');         $expander->set_use_markup(true);         // Put a little help text inside the expander         $help = new GtkLabel;         $help->set_alignment(0.2, 0.5);         $help->set_markup('Filling the form             In order to fill the form you must not to             leave Code, Description or Price empty...');                  $expander->add($help);         $expander->set_expanded(true);                  $vbox->pack_start($expander, false, false);                  parent::add($vbox);         parent::show_all();     }          /**      * Method onSaveClick      * Save the screen data to the database      */     public function onSaveClick()     {         // open the database         $conn = sqlite_open('data.db');                  // read the data from the entries         $product->code           = $this->entries[0]->get_text();         $product->description    = $this->entries[1]->get_text();         $product->amount         = $this->entries[2]->get_text();         $product->unit           = $this->entries[3]->get_text();         $product->cost           = $this->entries[4]->get_text();         $product->price          = $this->entries[5]->get_text();                  // sql instruction         $sql = "INSERT INTO products (code, description, amount," .                                     "unit, cost, price)" .                 "  VALUES ('{$product->code}',   '{$product->description}',"  .                 "          '{$product->amount}', '{$product->unit}'," .                 "          '{$product->cost}', '{$product->price}')";         // executes the sql         sqlite_query($conn, $sql);                  // closes the database         sqlite_close($conn);                  // clear the screen         $this->Clear();     }          /**      * Method Clear      * Clear all the entries from the form.      */     private function Clear()     {         for ($n=0; $n<=5; $n++)         {             $this->entries[$n]->set_text('');         }                  // focus the cursor to the first field         parent::set_focus($this->entries[0]);     }          /**      * Method Show      * Show all window      */     public function Show()     {         parent::show_all();     } } ?> The Products Listing In order to demonstrate the GtkTreeView component we'll build a little list of Products that will allow the user to edit its content, updating the data directly to the database. We'll also have a little explanation about the way GtkTreeView component work. GtkTreeView When developing graphic applications we are tempted to mix different aspects like the data model, the flow, the controls and the user interface in the same code. We know that the best practice is to separate these different aspects, also known as MVC pattern (model, view, controller). The new GtkTreeView component, different from its predecessores, allows these separation. The GtkTreeView widget can be used to show not only lists, but also tree in columns. GtkTreeView also allows to edit its data like a sheet. Who is long term Gtk developer must know the components GtkCTree and GtkCList, used before GtkTreeView. They were very simple to use, but also, too much limited in terms of functionalities, besides do not separate the data model from its exhibition. Despite complex, the component GtkTreeView, offers us a couple of new functionalities besides various renderers (images, check boxes, etc). In the GtkTreeView component the data model is completelly separated from its screen exhibition. The data are stored in the Model, that can be a GtkListStore (for listings) or GtkTreeStore (for trees). The GtkTreeView component is build with one or many columns, components of GtkTreeViewColumn type. Each column has a clickable header that can pack one or more cell renderers, components of GtkCellRenderer type (text, image, checkbox), responsible by the visualization of data stored in the data model. This separation between the model and its visualization allows one data model to be showed by different GtkTreeView's. This way, we can have one data model, but many ways to view it. The code below is used to show the products table on the screen, allowing the user to edit its data. All the View and Model are built by the __construct() method. In order to fill the model with the database values, we call the showData() method from the main interface. When the user edit any cell, automatically the method onEdit() is called performing an update to the database, passing the product code. This is the code of the Products List ProductList.class.php set_policy(GTK::POLICY_AUTOMATIC, GTK::POLICY_ALWAYS);                  // creates the treeview         $this->list = new GtkTreeView;         $scroll->add($this->list);                  // creates the model, with 6 elements         $this->model = new GtkListStore(Gtk::TYPE_STRING, Gtk::TYPE_STRING, Gtk::TYPE_STRING,                                         Gtk::TYPE_STRING, Gtk::TYPE_STRING, Gtk::TYPE_STRING);                  // creates the columns         $column1 = new GtkTreeViewColumn();         $column2 = new GtkTreeViewColumn();         $column3 = new GtkTreeViewColumn();         $column4 = new GtkTreeViewColumn();         $column5 = new GtkTreeViewColumn();         $column6 = new GtkTreeViewColumn();                  $column1->set_title('Code');         $column2->set_title('Description');         $column3->set_title('Amount');         $column4->set_title('Unit');         $column5->set_title('Cost');         $column6->set_title('Price');                  // define the renderers         $cell_renderer1 = new GtkCellRendererText();         $cell_renderer2 = new GtkCellRendererText();         $cell_renderer3 = new GtkCellRendererText();         $cell_renderer4 = new GtkCellRendererText();         $cell_renderer5 = new GtkCellRendererText();         $cell_renderer6 = new GtkCellRendererText();                  // connect the renderers when the user edit the data         $cell_renderer2->connect("edited", array($this, 'onEdit'), 1, 'description');         $cell_renderer3->connect("edited", array($this, 'onEdit'), 2, 'amount');         $cell_renderer4->connect("edited", array($this, 'onEdit'), 3, 'unit');         $cell_renderer5->connect("edited", array($this, 'onEdit'), 4, 'cost');         $cell_renderer6->connect("edited", array($this, 'onEdit'), 5, 'price');                  // pack the renderers         $column1->pack_start($cell_renderer1, true);         $column2->pack_start($cell_renderer2, true);         $column3->pack_start($cell_renderer3, true);         $column4->pack_start($cell_renderer4, true);         $column5->pack_start($cell_renderer5, true);         $column6->pack_start($cell_renderer6, true);                  // define the width         $cell_renderer1->set_property('width', 50);         $cell_renderer2->set_property('width', 180);         $cell_renderer3->set_property('width', 70);         $cell_renderer4->set_property('width', 50);         $cell_renderer5->set_property('width', 50);         $cell_renderer6->set_property('width', -1);                  // allow the user to edit the data         $cell_renderer2->set_property('editable', True);         $cell_renderer3->set_property('editable', True);         $cell_renderer4->set_property('editable', True);         $cell_renderer5->set_property('editable', True);         $cell_renderer6->set_property('editable', True);                  // define the model position that the renderers will be linked         $column1->set_attributes($cell_renderer1, 'text', 0);         $column2->set_attributes($cell_renderer2, 'text', 1);         $column3->set_attributes($cell_renderer3, 'text', 2);         $column4->set_attributes($cell_renderer4, 'text', 3);         $column5->set_attributes($cell_renderer5, 'text', 4);         $column6->set_attributes($cell_renderer6, 'text', 5);                  $this->list->append_column($column1);         $this->list->append_column($column2);         $this->list->append_column($column3);         $this->list->append_column($column4);         $this->list->append_column($column5);         $this->list->append_column($column6);                  $this->list->set_model($this->model);         $this->list->show_all();                  parent::add($scroll);         parent::show_all();     }     /**      * Method showData      * List all Products from database      */     public function showData()     {         // opens the database         $conn = sqlite_open('data.db');         // query the products         $query = sqlite_query($conn, 'select code, description, amount,'.                                      ' unit, cost, price from products');                  // read all data         while ($data = sqlite_fetch_array($query))         {             // insert a new line             $iter = $this->model->append();             $this->model->set($iter, 0, $data['code'],                                      1, $data['description'],                                      2, $data['amount'],                                      3, $data['unit'],                                      4, $data['cost'],                                      5, $data['price']);         }         // closes the database         sqlite_close($conn);     }     /**      * Method onEdit      * Called when the end user changes the data      */     public function onEdit($cell_renderer, $path, $new_text, $column_number, $column_name)     {         // get the selection         $treeselection = $this->list->get_selection();         list($model, $iter) = $treeselection->get_selected();                  // set the new value to the iterator         $model->set($iter, $column_number, $new_text);                  // get the first column         $code = $this->model->get_value($iter, 0);                  // opens the database         $conn = sqlite_open('data.db');                  // executes the update         $query = sqlite_query($conn, "update products set " . "$column_name='$new_text' where code='$code'");                  // closes the database         sqlite_close($conn);     } } ?> The Editor Another interesting new features of PHP-GTK2 are the components GtkTextView and GtkTextBuffer. In PHP-GTK1 we used GtkText component that now is deprecated, GtkText used to merge the visual and the content inside the same object. Now, using GtkTextView/GtkTextBuffer it's possible to manage separatelly the content (wich is stored in a GtkTextBuffer object) and the View (that is represented by GtkTextView object). This way, the same TextBuffer can be shown by different TextView's, the same way it happens with GtkTreeView widget. GtkTextBuffer also offer us iterators, that is the possibility of bookmark some positions in the text. It's very usefull to write an editor encapsulating some functions to embed it in our applications, providing some basic operations like Open and Save, Copy and Paste, among others, depending on the demand. Through this sample below, we'll build a little text editor with a toolbar containing two buttons (open and save), a scrolling bar and a TextView/TextBuffer component. This editor performs basic operations like openning and saving the file, with a few lines of code. FileDialogs The widget PHP-GTK1 offered us to deal with files (open, save, etc...) was GtkFileSelection. Very easy to use and a very simple interface. Not very user-friendly for those ones used to file dialogs from another Operation Systems. For Gtk2 and it's bindings, Federico de Mena Quintero, one of the most active Gtk hackers wrote GtkFileChooser, a new FileDialog, with a better look and more extensible. Now GtkFileChooser is used practically by all Gnome based applications, such as Evolution, Gnumeric, Gaim, Gimp and others. Our Text Editor will also use GtkFileChooser for Open and Save operations. This is the code of the Text Editor, the __construct() method set the interface, instantiates the TextView/TextBuffer objects, the buttons and the scrolling window. When the user clicks on the Open button, the method onOpen() is called, reading the file and filling the TextBuffer and when he clicks on the Save button, the method onSave() is calling, reading the TextBuffer and storing its content in the file selected by the user. TextEditor.class.php set_label('save');         $save->set_stock_id('gtk-save');         $save->connect('clicked', array(&$this, 'saveFile'));                  // Creating the open button         $open = new GtkToolButton;         $open->set_label('open');         $open->set_stock_id('gtk-open');         $open->connect('clicked', array(&$this, 'openFile'));                  // Insert the buttons on toolbar         $toolbar->insert($open, 0);         $toolbar->insert($save, 0);                  $vbox->pack_start($toolbar, false, false);                  // Creating the scroll         $scroll = new GtkScrolledWindow;                  // Creating the duo TextView/TextBuffer;         $this->textview = new GtkTextView;         $this->textbuffer = new GtkTextBuffer;         $this->textview->set_buffer($this->textbuffer);                  // Putting the textview inside the Scrolling         $scroll->add($this->textview);         $vbox->pack_start($scroll, true, true);                  # Add the Vertical box to the window         parent::add($vbox);         parent::show_all();     }     /**      * Method openFile      * Shows the FileDialog and puts the file contents      * inside the TextBuffer      */     public function openFile()     {         // Creates the FileChooserDialog         $dialog = new GtkFileChooserDialog('Opening the file', NULL,                       Gtk::FILE_CHOOSER_ACTION_OPEN,                       array(Gtk::STOCK_OK,     Gtk::RESPONSE_OK,                             Gtk::STOCK_CANCEL, Gtk::RESPONSE_CANCEL));                                      // Shows the FileChooserDialog         $response = $dialog->run();                  if ($response == Gtk::RESPONSE_OK) // if the user has clicked OK         {             // Clear the TextBuffer             $first = $this->textbuffer->get_start_iter();             $end   = $this->textbuffer->get_end_iter();             $this->textbuffer->delete($first, $end);                          // Insert the file's content inside the TextBuffer.             $this->textbuffer->insert_at_cursor(file_get_contents($dialog->get_filename()));         }         $dialog->destroy();     }     /**      * Method saveFile      * Shows the FileDialogs and write the TextBuffer      * contents to the selected file.      */     public function saveFile()     {         // Creates the FileChooserDialog         $dialog = new GtkFileChooserDialog('Saving the file', NULL,                       Gtk::FILE_CHOOSER_ACTION_SAVE,                       array(Gtk::STOCK_OK,     Gtk::RESPONSE_OK,                             Gtk::STOCK_CANCEL, Gtk::RESPONSE_CANCEL));                                      // Shows the FileChooserDialog         $response = $dialog->run();                  if ($response == Gtk::RESPONSE_OK)  // if the user has clicked OK         {             // Get the TextBuffer content             $first = $this->textbuffer->get_start_iter();             $end   = $this->textbuffer->get_end_iter();             $text = $this->textbuffer->get_text($first, $end);                          // Write the TextBuffer content inside the file.             file_put_contents($dialog->get_filename(), $text);         }         $dialog->destroy();     } } ?> AboutDialog Our Interface wouldn't be complete without an about dialog showing the application logo with some text. This sample will be usefull to demonstrate two aspects. The first one is the new way of dealing with images, the second one is to demonstrate the usage of exceptions in PHP-GTK2. Images PHP-GTK1 supports native .xpm image files. The XpixMap (XPM) format consists of an ASCII image format. The format defines how to store color images. Despite easy to use and open, XPM files are not widely used yet and are not indicated for high resolution images because its size increases rapidly. An alternative for PHP-GTK1 was enable the library GdkPixbuf, that deals with the most popular image formats like PNG, JPEG and others. Since GTK2, GdkPixbuf is not optional anymore, it's now part of the set of available native classes. It's very usefull to have a native way to deal with these common image formats. It's very common need to load specific images to use as icons of menus. This way we don't to use thirdy part tools for image conversion. Exceptions PHP5 now support exceptions and PHP-GTK take advantage generating exceptions under some situations like errors that occurs during the object construction, in methods that use the Gerror mechanism, such as static constructors like GdkPixbuff::new_from_file() and in codepage conversions. Our sample use exceptions to control the image exibition. If our Logo is not found, it'll generate a exception controlled bye the main flow of our AboutDialog class. This is the code of the AboutDialog AboutDialog.class.php set_from_pixbuf($pixbuf);                          $vbox->pack_start($imagem);         }         catch (PhpGtkGErrorException $error)         {             // if any error ocurrs, show it on the screen             $dialog = new GtkMessageDialog(null, Gtk::DIALOG_MODAL, Gtk::MESSAGE_ERROR,                                            Gtk::BUTTONS_OK, $error->message);                          $response = $dialog->run();             $dialog->destroy();             return;         }         // show the text about the application         $this->label = new GtkLabel($text);         $vbox->pack_start($this->label);         // creates the "Close" button         $this->button = new GtkButton('Close');         $this->button->connect('clicked', array($this, 'onClose'));         $vbox->pack_start($this->button, false, false);                  parent::show_all();     }     /**      * Method onClose      * Closes the window      */     public function onClose()     {         parent::destroy();     }          /**      * Method __destruct      * Called whenever the user closes the dialog      */     public function __destruct()     {         echo "byebye\n";     } } ?> References: Zmievski, Andrei. Say "hello" to PHP-GTK2. International PHP Conference 2005; PS: Pablo Dall'Oglio (pablo@dalloglio.net) is author of the first book about PHP-GTK of the world. He is also author of Agata Report Tulip Editor and Coordinator of GNUTeca project (www.gnuteca.org.br) (an open source software for library management).