120 likes | 318 Views
Προγραμματισμός με GTK. ΠΑΡΟΥΣΙΑΣΗ ΣΤΑ ΠΛΑΙΣΙΑ ΤΟΥ ΜΑΘΗΜΑΤΟΣ «ΕΠΙΚΟΙΝΩΝΙΑ ΑΝΘΡΩΠΟΥ-ΜΗΧΑΝΗΣ» ΑΛΕΞΑΝΔΡΟΣ Κ. ΓΙΔΑΡΑΚΟΣ kanenas2005@yahoo.gr parsifal@cs.uoi.gr. Δημιουργία GUI με υψηλού επιπέδου Widget Toolkits. Μερικές γενικές αρχές
E N D
Προγραμματισμός με GTK • ΠΑΡΟΥΣΙΑΣΗ ΣΤΑ ΠΛΑΙΣΙΑ ΤΟΥ ΜΑΘΗΜΑΤΟΣ «ΕΠΙΚΟΙΝΩΝΙΑ ΑΝΘΡΩΠΟΥ-ΜΗΧΑΝΗΣ» • ΑΛΕΞΑΝΔΡΟΣ Κ. ΓΙΔΑΡΑΚΟΣ • kanenas2005@yahoo.gr • parsifal@cs.uoi.gr
Δημιουργία GUI με υψηλού επιπέδου Widget Toolkits • Μερικές γενικές αρχές • 1. Διεπαφή Σύνολο αντικειμένων (Widgets), συνδεδεμένα μεταξύ τους με σχέσεις ιεραρχίας, εν είδει «δένδρου» • 2. Κάποια Widgets υποστηρίζουν αλληλεπίδραση με τον χρήστη (ετικέτες, κουμπιά, check boxes) • 3. Άλλα λειτουργούν ως δοχεία (containers) που ομαδοποιούν τα υπόλοιπα Widgets (παράθυρα, panels) • 4. Τα περιεχόμενα του «δένδρου» των Widgets καθώς και οι ιδιότητές τους μπορούν να μεταβάλλονται κατά το χρόνο εκτέλεσης • 5. Χειρισμός των γεγονότων χρήστη (user events) Βιβλιοθήκη • 6. Ενέργεια που ακολουθεί την ανίχνευση ενός event Ευθύνη του κυρίως κώδικα της εφαρμογής (back-end)
Και ποια η χρησιμότητά τους; • Τα περισσότερα σύγχρονα Λ/Σ προσφέρουν επαρκή μεν, δύσχρηστα δε Native APIs για τη δημιουργία GUI. Τα Toolkits, προσθέτοντας ένα επιπλέον επίπεδο αφαίρεσης σε αυτόν τον τομέα, επιτρέπουν: • 1. Ευκολότερη συγγραφή κώδικα • 2. Ταχύτερη ανάπτυξη της εφαρμογής R.A.D. Φιλοσοφία • 3. Δημιουργία πολύπλοκων και εντυπωσιακών γραφικών διεπαφών, με την υλοποίηση χαρακτηριστικών που δεν παρέχονται από τα Native APIs • 4. Δημιουργία ενοποιημένων σε εμφάνιση και συμπεριφορά, περιβαλλόντων χρήσης Ομαλότερη καμπύλη εκμάθησης για το χρήστη • 5. Περισσότερο μεταφερτό κώδικα σε διαφορετικές πλατφόρμες
Και ποια η χρησιμότητά τους; Χωρίς επίπεδα αφαίρεσης και αυτοματισμούς στον προγραμματισμό όπως αυτά που προσφέρουν τα Toolkits, τα γραφικά περιβάλλοντα που χρησιμοποιούμε άραγε θα ήταν τόσο εμφανίσιμα όπως στο παράδειγμα (GNOME) και θα ολοκληρωνόταν η ανάπτυξή τους σε λογικό χρόνο...;
Στα ενδότερα του GTK (1) • #include <gtk/gtk.h> • static gint delete_event_cb(GtkWidget* w, GdkEventAny* e, gpointer data); • static void button_click_cb(GtkWidget* w, gpointer data); • int main(int argc, char* argv[]) { • GtkWidget* window; • GtkWidget* button; • GtkWidget* label; • gtk_init(&argc, &argv); • window = gtk_window_new(GTK_WINDOW_TOPLEVEL); • button = gtk_button_new(); • label = gtk_label_new("Hello, World!"); • gtk_container_add(GTK_CONTAINER(button), label); • gtk_container_add(GTK_CONTAINER(window), button); • gtk_window_set_title(GTK_WINDOW(window), "Hello"); • gtk_container_set_border_width(GTK_CONTAINER(button), 10); • gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event_cb), NULL); • gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(button_click_cb), label); • gtk_widget_show_all(window); • gtk_main(); • return 0; • } • static gint delete_event_cb(GtkWidget* window, GdkEventAny* e, gpointer data) { • gtk_main_quit(); • return FALSE; • } • static void button_click_cb(GtkWidget* w, gpointer data) { • GtkWidget* label; • gchar* text; • gchar* tmp; • label = GTK_WIDGET(data); • gtk_label_get(GTK_LABEL(label), &text); • tmp = g_strdup(text); • g_strreverse(tmp); • gtk_label_set_text(GTK_LABEL(label), tmp); • g_free(tmp); • } Ένα «μικρό»* HelloWorld :p * Στην Πληροφορική, όπως και στη ζωή, έννοιες όπως «απλό», «μικρό», «γρήγορο» κλπ, είναι πάντα σχετικές...! :)
Στα ενδότερα του GTK (2) • Και όμως, είναι απλό! • 1. Περισσότερο χρησιμοποιούμενη γλώσσα προγραμματισμού η C (υπάρχουν bindings και για πολλές άλλες δημοφιλείς γλώσσες) • 2. Με βασικές γνώσεις C Εύκολη κατανόηση της λογικής πίσω από ένα πρόγραμμα σε GTK, ακόμη και χωρίς πρότερη επαφή με αυτό • 3. Η συγγραφή GTK κώδικα είναι συστηματική διαδικασία περιλαμβάνει πολλές επαναληπτικές διαδικασίες Η άνεση στη χρήση είναι θέμα αρχικής εξοικείωσης • 4. Παρέχεται στην εγκατάσταση πλήρης τεκμηρίωση. Ελεύθερη πρόσβαση σε πλήθος οδηγών και παραδειγμάτων στο Διαδίκτυο
Στα ενδότερα του GTK (3) • Σημεία - κλειδιά • 1.#include <gtk/gtk.h> • Εκεί δηλώνονται μεταβλητές, συναρτήσεις και δομές που χρησιμοποιούνται σε GTK προγράμματα • 2.gtk_init(&argc, &argv); • Αρχικοποιεί για χρήση τη βιβλιοθήκη, τους εξ ορισμού χειριστές σημάτων (signal handlers). Ελέγχει για τυχόν GTK-specific ορίσματα που δόθηκαν κατά την εκκίνηση του προγράμματος • 3.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); • button = gtk_button_new(); • label = gtk_label_new("Hello, World!"); • (έχουν δηλωθεί προηγουμένως αντίστοιχα τα: • GtkWidget* window; • GtkWidget* button; • GtkWidget* label;)
Αντικειμενοστρέφεια σε C;;; • 1. Υλοποίηση custom συστήματος αντικειμένων Αντικειμενοστρεφή χαρακτηριστικά (κληρονομικότητα-εικονικές συναρτήσεις) • 2. Προσανατολισμός στο χρόνο εκτέλεσης Ευκολότερη ανάπτυξη bindings και οπτικών εργαλείων για το GTK σε managed (interpreted) γλώσσες • 3. Βασικά αντικείμενα τα widgets: Υποκλάσεις της βασικής κλάσης GtkWidget • 4. Αναφορά σε widgets με δείκτη GtkWidget* • Δημιουργία/αρχικοποίηση gtk_<widgetname>_new() • Επιστρέφει δείκτη τύπου GtkWidget* προς το νέο αντικείμενο • 5. Χειρισμός αντικειμένων με χρήση των μεθόδων του • Ξεκινούν με το όνομα του τύπου στον οποίον επενεργούν και δέχονται ως πρώτο όρισμα δείκτη προς αντικείμενο τέτοιου τύπου. • 6. Π.χ: gtk_container_add(GTK_CONTAINER(button), label); • Πρώτο όρισμα ένας δείκτης GtkContainer* • Η μακροεντολή GTK_CONTAINER() εκτελεί casting του GtkWidget*, απαραίτητο αφού η C δεν αντιλαμβάνεται εγγενώς σχέσεις κληρονομικότητας.
HelloWorld revisited... • Έχοντας τα προηγούμενα υπ'όψιν μας, μπορούμε πιο άνετα να επανεξετάσουμε το παράδειγμα HelloWorld: • window = gtk_window_new(GTK_WINDOW_TOPLEVEL); • button = gtk_button_new(); • label = gtk_label_new("Hello, World!"); • gtk_container_add(GTK_CONTAINER(button), label); • gtk_container_add(GTK_CONTAINER(window), button); • gtk_window_set_title(GTK_WINDOW(window), "Hello"); • gtk_container_set_border_width(GTK_CONTAINER(button), 10); • Αυτό το τμήμα κώδικα δημιουργεί ένα παράθυρο, ένα κουμπί και μία ετικέτα (γραμμή κειμένου). Τοποθετεί την ετικέτα εντός του κουμπιού και το κουμπί εντός του παραθύρου. Στη συνέχεια, ορίζει τον τίτλο του παραθύρου και προσθέτει ένα μικρό περίγραμμα γύρω από το κουμπί:
Signals • 1. Ενέργεια χρήστη επάνω σε ένα widget Αντίδραση από μέρους της εφαρμογής. • 2. Αυτό επιτυγχάνεται με τα signals Σήματα που εκπέμπει ένα widget (γενικώς κάθε instance κλάσης GtkObject) όταν αλληλεπιδρούμε με αυτό με συγκεκριμένο τρόπο • 3. Συνδέουμε στο σήμα μία callback συνάρτηση Αναλαμβάνει ναδώσει την κατάλληλη απάντηση • 4. Με χρήση της gtk_signal_connect: • gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event_cb), NULL); • gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(button_click_cb), label); • 5. Ορίσματα: Το αντικείμενο που θα παρακολουθείται, το σήμα και η callback συνάρτηση τα οποία συνδεόνται και ένα user_data όρισμα. • 6.gtk_widget_show_all(window); Εμφανίζει το παράθυρο (καλώντας αναδρομικά μία gtk_widget_show στο αντικείμενο window και όλα τα περιεχόμενά του) • gtk_main(); Φέρνει το πρόγραμμα σε κατάσταση αναμονής για είσοδο από το χρήστη.
Σχεδιασμός του interface • 1. Ιδιομορφία του GTK στη σχεδιάση των layouts: Δεν είναι free-form • 2. Δημιουργούμε containers που θα δέχονται ως περιεχόμενα τα διάφορα widgets που θα χρησιμοποιήσουμε • 3. Abstract βασική κλάση η GtkContainer • 4. Παράδειγματα υποκλάσεων: • GtkVBox • (κάθετη διάταξη των «παιδιών») GtkTable («παιδιά» σε μορφή πίνακα)
Πηγές • 1. GTK+ Official Website: • http://www.gtk.org • 2. GTK+ 2.0 Official Tutorial: • http://www.gtk.org/tutorial/ • 3. Widget toolkits - Wikipedia: • http://en.wikipedia.org/wiki/Widget_toolkit • 4. GTK+ - Wikipedia: • http://en.wikipedia.org/wiki/GTK+ (GTK logo) • 5. GTK+ / Gnome Application Development: • http://developer.gnome.org/doc/GGAD/