int21h

GUI pod pascalem

Proč o tom vlastně píšu? Asi proto, že abyste získali práci jako programátor, tak už nikoho nezajímá, že umíte nahodit vesu přes assembler. Je potřeba umět dnešní trendy. Náš časopis sice není o dnešních trendech, ale je hlavně o pascalu. Chci ukázat, že pascal není pozadu ani v těchto odvětvích.

Hlavním rozdíl mezi TurboPascalem a FreePascalem je ten, že FreePascal je programovací jazyk se vším všudy, podobně jako c, a TurboPascal je jen učební učební pomůcka, která vás uvede do světa programování (i když někdo v něm zůstane navždy). Pokudmáte v rukou FreePascal, tak se můžete klidně pustit i do vytváření GUI aplikací.

V tomto díle bych se chtěl vysvětlit základní práci s GUI.


Nebudu se zabývat WinAPI, protože je to fakt zbytečný. Raději vám představím Gtk (Gimp ToolKit), který je přenosný na všechny platformy a nabízí stejné možnosti jako WinAPI.

Potřebujete tyto knihovny:
glib gtk gdk(grafika)
knihovna gdk se využívá hlavně ke grafice (formáty obrázků).

Důležité je, že gtk zavádí nové datové typy.
Hlavně:
PGtkWidget - jakýkoli objekt
pchar - to je pointer na char, takže string (podobné z c)

A teď teorie Gtk.

Gtk v pascalu a v c není objektové! Proto to vypadá tak složitě, ale

Hlavní okno se dělí na boxy (containery). Boxy jsou vertikální a horizontální. Každý box může obsahovat objekty (i další boxy) a tak můžete postavit celou aplikaci.

Struktura příkladu, který uvedu na konci je asi taková:

GtkWindow
+-GtkVBox
  +-GtkLabel
  +-GtkButton  
Nejlepší je vše si navrhnout předem na papír nebo nějáho graf. editoru.
Výborné jsou také vývojové prostředí jako Glade. I když Glade je dělaný přímo na vytváření projektů, já preferuji to, že si to nejdřív navrhnu v Glade a pak to napíšu ve vim:) Mě vyhovuje, když si kód píšu sám.
Nevím, jestli je Glade také pro ostatní platformy než Linux, ale měl by být.

Další věc co je nutné znát jsou signály (events,callbacks,signals). Každý objekt vyvolá při aktivaci nějákou událost. Tuto událost můžeme odchytit a zpracovat.


Praxe:
Funkce budu popisovat rovnou v kódu:
program HelloWorld;


uses glib,gtk,gdk;


var window, {Hlavni okno}
    glabel, {Retezec}
    gbutton,{Tlacitko}
    vbox:   {Vertikalni Box}
     PGtkWidget;
    
{Tyto procedury preskocte a vratte se az budete u definovani signalu}
procedure quit(widget:PGtkWidget;event:PGdkEvent;data: pgpointer);cdecl;
{To vsecho widget posila: Co je zac, jakou udalosti byl vyvolan a data, ktera byla poslana}
begin
 gtk_main_quit(); {Jedina funkce, ktera dokaze vyskocit z hlavniho loopu. Nepouzivejte halt!}
end;
procedure hello(widget:PGtkWidget;event:PGdkEvent;data: pgpointer);cdecl;
begin
 writeln('hello');
end; 


Begin
 gtk_init(@argc, @argv); {Tohle je jasne z cecka}


 window:=gtk_window_new(GTK_WINDOW_TOPLEVEL);{Nove okno}
 gtk_widget_set_usize(PGtkWIDGET(window),125,90);{Neni to objektove, tak to vypada slozite}
 gtk_window_set_title(GTK_WINDOW(window), 'Test program');
 
 vbox:=gtk_vbox_new(true,0); {homogenous,spacing}
 gtk_container_add(PGtkCONTAINER(window),vbox); {A o tom to cely je}
 glabel:=gtk_label_new('');
 gtk_label_set_text(PGtkLABEL(glabel), 'Press button to exit');
 {Ted bude pridani glabel do vbox, ktery uz je ve window - strukturovanost}
 gtk_box_pack_start(PGtkBOX(vbox), glabel,true,true,0);{S temito paremetry si musite pohrat}
 GTK_WIDGET_SET_FLAGS(glabel,gtk_CAN_DEFAULT);{Priznam se, tady nevim o co tu jde}


 gbutton:=gtk_button_new_with_label('Hello, world!');
 gtk_widget_set_usize(PGtkWIDGET(gbutton),1, 1);
 gtk_box_pack_start(PgtkBOX(vbox), gbutton, true, true,0);
 GTK_WIDGET_SET_FLAGS(gbutton, gtk_CAN_DEFAULT);
 gtk_widget_grab_default(gbutton);
 
 gtk_widget_show_all(window); {Ukaze vse co widget obsahuje} {SIGNALY}
 {Ted jde do tuheho}
 gtk_signal_connect(Gtk_OBJECT(window), 'delete_event', GTK_SIGNAL_FUNC(@quit), NIL);
 {delete_event je ten krizek na okne. Nazvy vsech udalosti jdou nalezt k tutorialu gtk}
 {Posledni dva parametry jsou kterou funkci provest a pak pointer na data, ktera se maji funkci poslat}
 gtk_signal_connect(PGtkOBJECT(gbutton), 'clicked', GTK_SIGNAL_FUNC(@hello), NIL);


 gtk_main(); {A od ted se vsechno rozjede}
End.  

Jen pro zajímavost: tady je ten samý kód v c, perlu a pythonu

C
Tady se to vyuziva asi nejvic.
Vsimnete si, ze je to naprosto to same jako v pascalu
#include 
#include 


int quit(GtkWidget *widget,gpointer data) {
        gtk_main_quit();
        return 0;
}
        
int hello(GtkWidget *widget,gpointer data) {
        printf("Hello, world!");
        return 0;
}


int main(int argc,char *argv[]) {
        GtkWidget *window,*gbutton,*glabel,*vbox;
        
        gtk_init(&argc,&argv);


        window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_widget_set_usize(GTK_WIDGET(window),125,90);
        gtk_window_set_title(GTK_WINDOW(window),"Test program");


        vbox=gtk_vbox_new(TRUE,0);
        gtk_container_add(GTK_CONTAINER(window),vbox);
        glabel=gtk_label_new("Press button to exit");
        gtk_box_pack_start(GTK_BOX(vbox),glabel,TRUE,TRUE,0);


        gbutton=gtk_button_new_with_label("Hello, world!");
        gtk_widget_set_usize(gbutton,1,1);
        gtk_box_pack_start(GTK_BOX(vbox), gbutton,TRUE,TRUE,0);


        gtk_widget_show_all(window);
        
        gtk_signal_connect(GTK_OBJECT(window),"delete_event",GTK_SIGNAL_FUNC(quit),NULL);
        gtk_signal_connect(GTK_OBJECT(gbutton),"clicked",GTK_SIGNAL_FUNC(hello),NULL);
        gtk_main();
        
        return 0;
}  

Perl
Tohle uz je uplne o necem jinem, protoze je to objektove.
#!/usr/bin/perl


use Gtk;


init Gtk;


my $window = new Gtk::Window("toplevel");
my $vbox = new Gtk::VBox(0,0);
my $glabel = new Gtk::Label("Press butoon to exit");
my $gbutton = new Gtk::Button("Hello, world!");


$window->set_usize(125,90);


$window->signal_connect("delete_event", &quit);
$gbutton->signal_connect("clicked", &hello);


$vbox->pack_start($glabel,1,1,0);
$vbox->pack_start($gbutton,1,1,0);
$window->set_title("Hello, world!");
$window->add($vbox);
$window->show_all();


main Gtk;


sub quit {
        Gtk->exit(0);
}


sub hello {
        print "Hello, world!";
}  

Python
A nakonec můj nejmilejší.
#!/usr/bin/python


from gtk import *


def quit(*args):
        mainquit()


def hello(*args):
        print 'Hello, world'


window = GtkWindow(WINDOW_TOPLEVEL)
window.set_title("Test program")
window.set_usize(125,90);


vbox = GtkVBox(0,0);


glabel = GtkLabel("Press button to exit");
gbutton = GtkButton("Hello, World!")
vbox.pack_start(glabel,1,1,0);
vbox.pack_start(gbutton,1,1,0);


window.add(vbox);


window.connect("delete_event", quit)
gbutton.connect("clicked", hello)


window.show_all()


mainloop()  

Závěr

Těmito kódy jsem chtěl říct, že pokud se naučíte pracovat s Gtk v pascalu nebo v c, tak už pro vás nebude žádný problém napsat program v jazyce jiném. Názvy funkcí a objektů jsou víceméně podobné.

A ještě něco. Radím vám: NEPOUŽÍVEJTE WINAPI!

2006-11-30 | BOby
Reklamy:
„Přátelství je součást lidského štěstí.“ Jan Werich