Προγραμματισμός με GTK(...): Tοποθέτηση των widgets
Description: This is issue 20 of Magaz, the Hellenic LinuxMagazine
Keywords: magaz hellenic greek hellas greece hellug linux magazine

Magaz, The Greek Linux Magazine
Τεύχος #20
Περιληπτικά Περιεχόμενα Αναλυτικά Περιεχόμενα Mirrors Links Πληροφορίες Συντάκτες Αναζήτηση Επικοινωνία
Προηγούμενο Περιεχόμενα ### 5. Tοποθέτηση των widgets Το πιο πιθανό είναι να μην δημιουργήσουμε ποτέ μια εφαρμογή που θα έχει μονάχα ένα widget, όπως στην περίπτωση του HelloMagez. Μάλλον, αυτό που θα θέλουμε να κάνουμε θα αποτελείται από περισσότερα από ένα widget. Ας δούμε πως μπορούμε να τα τοποθετήσουμε στο παράθυρο του προγράμματός μας. ### 5.1 Boxes, ή αλλιώς κουτιά :) Τα boxes θα γίνουν οι καλύτεροι φίλοι μας στη διαδικασία σύνταξης εφαρμογών για gtk, αλλά - πιστέψτε με - και οι χειρότεροί μας εχθροί. Θα μάθουμε να ζούμε με τα boxes, και να είστε σίγουροι ότι δεν θα τα γλιτώσουμε. Τι είναι όμως αυτά τα boxes; Είναι widgets, όπως και όλα τα άλλα. Απλά, μπορούν να περιέχουν περισσότερα από 1 widgets πάνω τους. Δεν είναι ορατά, και χρησιμοποιούνται μονάχα για την ομαδοποίηση αντικειμένων. Τα boxes μπορεί να είναι δύο ειδών, ανάλογα με τον προσανατολισμό που θέλουμε να πάρουν τα προς τοποθέτηση σε αυτό widgets: HORIZONTAL BOXES Τα τοποθετημένα σε αυτό widgets θα μπουν στη σειρά από αριστερά προς τα δεξιά ή από τα δεξιά προς τα αριστερά όπως θα δούμε παρακάτω στην εξήγηση των συναρτήσεων `gtk_box_pack_start` και `gtk_box_pack_end`. H δημιουργία ενός τέτοιου box επιτυγχάνεται με τη χρήση της συνάρτησης `gtk_hbox_new`. VERTICAL BOXES Τα τοποθετημένα σε αυτό widgets θα μπουν στη σειρά από πάνω προς τα κάτω ή από κάτω προς τα πάνω, πάλι με χρήση των `gtk_box_pack_start` και `gtk_box_pack_end`. Σε γενικές γραμμές, η δημιουργία ενός τέτοιου box επιτυγχάνεται με τη χρήση της συνάρτησης `gtk_hbox_new`. #### Δημιουργία, σύνταξη και παραμέτροι. Για τη δημιουργία ενός box, χρησιμοποιούμε τις `gtk_hbox_new` και `gtk_vbox_new` όπως αναφέραμε και παραπάνω. Η σύνταξη και ο τύπος των συναρτήσεων αυτών είναι:
    GtkWidget *gtk_hbox_new(gint homogeneous, gint spacing);
    GtkWidget *gtk_vbox_new(gint homogeneous, gint spacing);
Στη συνέχεια θα αναφέρομαι μονάχα στην εντολή `gtk_hbox_new` και ότι ισχύει για αυτήν ισχύει και για την `gtk_vbox_new`. `Οπως παρατηρούμε, επιστρέφει τιμή τύπου `GtkWidget`, και παίρνει δύο τιμές, τύπου gint, τις homogenous και spacing. Η homogenous μπορεί να είναι TRUE ή FALSE (και φυσικά οποιαδήποτε λογική έκφραση) και μας δίνει τη δυνατότητα να ελέγξουμε αν τα widgets που θα τοποθετηθούν στο box θα έχουν το ίδιο πλάτος όλα ή όσο χρειάζεται το κάθε ένα. Η παράμετρος spacing καθορίζει πόσα pixels θα απέχουν μεταξύ τους τα widgets. #### Εργασία με τα boxes Δεν πιστεύω να σας τρόμαξα με τα όσα έγραψα για τα boxes στην προηγούμενη ενότητα... `Οπως θα δείτε, η εργασία με τα boxes είναι μια εύκολη υπόθεση, αν ξέρετε να δουλεύετε τις συναρτήσεις `gtk_box_pack_start` και `gtk_box_pack_end`. Στη συνέχεια θα δούμε πόσο εύκολη είναι η εργασία με αυτές τις συναρτήσεις. `gtk_box_pack_start` `gtk_box_pack_end` Η μορφή αυτών των συναρτήσεων είναι:
    void gtk_box_pack_start(GtkBox *box, GtkWidget *child, gint expand, gint fill, gint padding );
    void gtk_box_pack_end(GtkBox *box, GtkWidget *child, gint expand, gint fill, gint padding );
Δεν επιστρέφουν καμία τιμή (είναι void απ' ότι βλέπετε) και τα ορίσματα που δέχονται εξηγούνται παρακάτω: `GtkBox *box` Το όνομα του box στο οποίο αναφερόμαστε. `GtkWidget *child` Το όνομα του widget το οποίο προσθέτουμε. `gint expand` Είναι μορφής gint, και αυτό που περιγράφει είναι αν το widget που τοποθετούμε θα πιάνει όλη την περιοχή του box. Μπορούμε να του αποδώσουμε τις τιμές TRUE και FALSE. TRUE στην περίπτωση που θέλουμε να πιάνει όλη την διαθέσιμη περιοχή, και FALSE αν θέλουμε να πιάνει μόνο όση περιοχή του είναι απαραίτητη. Δίδοντας την τιμή FALSE μπορούμε να επιτύχουμε (αριστερή στην περίπτωση της `gtk_box_pack_start` ή δεξιά στην περίπτωση της `gtk_box_pack_end`) στοίχιση. `Οπως καταλαβαίνετε, αν δοθεί η τιμή TRUE, δεν έχει σημασία πια από τις `gtk_box_pack_start` ή `gtk_box_pack_end` χρησιμοποιήσουμε. `gint fill` Η τιμή αυτής της παραμέτρου έχει σημασία μόνο αν η τιμή της `expand` είναι TRUE. Και αυτό γιατί περιγράφει αν ο επιπλέον χώρος που μένει μετά τη δημιουργία των widgets θα ανήκει σε αυτά (Δηλ. θα τα μεγαλώσει) στην περίπτωση που πάρει την τιμή TRUE ή αν θα ανήκει στο box σαν αδιάθετος χώρος στην περίπτωση που της δώσουμε την τιμή FALSE `gint padding` Αριθμός τύπου gint, που καθορίζει πόσος χώρος (σε pixels) γύρω από το κάθε widget δεν θα χρησιμοποιείται. ### 5.2 Tοποθέτηση των widgets, partII (λέγε με tables) Υπάρχει και άλλος ένας τρόπος για να στοιχίσουμε τα widgets στο παράθυρο της εφαρμογής μας. Αυτός επιτυγχάνεται με τη χρήση της συνάρτησης `gtk_table_new` που δημιουργεί έναν πίνακα στο παράθυρο της εφαρμογής μας. Φυσικά, και αυτή η συνάρτηση χρησιμοποιείται μόνο για την τοποθέτηση των διαφόρων widgets στο παράθυρο, και δεν σχεδιάζεται κανένας πίνακας στην εφαρμογή μας. Η σύνταξή της είναι η εξής:
    GtkWidget *gtk_table_new(gint rows, gint columns, gint homogeneous );
Είναι προφανές ότι rows είναι ο αριθμός των γραμμών του πίνακά μας και columns ο αριθμός των στηλών του. Το homogenous περιγράφει τον τρόπο που τα κελιά του πίνακα θα διανέμονται και θα τοποθετούνται πάνω στο παράθυρό μας. Αν είναι TRUE, τότε όλα τα κελιά του πίνακα μεγαλώνουν ή μικραίνουν, σύμφωνα με το μεγαλύτερο widget στον πίνακα. Αν πάρει την τιμή FALSE, το μέγεθος ορίζεται από το πιο μακρύ widget στην κάθε στήλη και το πιο ψηλό widget στην σειρά. Αυτό που ουσιαστικά συμβαίνει είναι ότι αν το HOMOGENEOUS είναι TRUE, όλα τα widgets έχουν το ίδιο μέγεθος, και είναι ομοιόμορφα τοποθετημένα πάνω στο box. Η διάταξη των κελιών του πίνακα, διαμορφώνεται από το 0 μέχρι τις τιμές rows και columns. Μoιάζει δηλαδή με το παρακάτω. Η αρίθμηση όπως βλέπετε, ξεκινάει από την πάνω αριστερή γωνία.
          0          1          2
         0+----------+----------+
          |          |          |
         1+----------+----------+
          |          |          |
         2+----------+----------+
Για την τοποθέτηση ενός widget σε ένα πίνακα, χρησιμοποιούμε την συνάρτηση `gtk_table_attach`, της οποίας η σύνταξη είναι η παρακάτω
    void gtk_table_attach(GtkTable  *table, GtkWidget *child, gint left_attach, gint right_attach,
                          gint top_attach, gint bottom_attach, gint xoptions,
                          gint yoptions, gint xpadding, gint ypadding);
Δεν επιστρέφei καμία τιμή και τα ορίσματα που δέχεται είναι `GtkTable *table` Το Table στο οποίο αναφερόμαστε `GtkWidget *child` Το widget που θέλουμε να τοποθετήσουμε `gint left_attach` Η αριστερή συντεταγμένη από όπου θα αρχίζει το widget `gint right_attach` Η δεξιά συντεταγμένη από όπου θα τελειώνει το widget `gint top_attach` Η πάνω συντεταγμένη από όπου θα αρχίζει το widget `gint bottom_attach` Η κάτω συντεταγμένη που θα τελειώνει το widget `gint xoptions` χρησιμοποιείται για τον καθορισμό του τρόπου πακεταρίσματος, και θα το δούμε στη συνέχεια πιο αναλυτικά `gint yoptions` `Οπως και το παραπάνω, και οι τιμές που μπορεί να πάρει τόσο αυτό όσο και το `xoptions` είναι οι παρακάτω: `GTK_FILL` Αν η περιοχή (συνήθως το κουτί του πίνακα) είναι μεγαλύτερο από το widget που τοποθετούμε, το widget θα μεγαλώσει τόσο ώστε να καλύψει όλο τον χώρο που υπάρχει. `GTK_SHRINK` Αν κατά την απόδοση χώρου σε ένα κουτί ο χώρος που δίνεται σε ένα widget είναι μικρότερος από το μέγεθός του ίδιου του widget, τότε αυτό θα μικράνει ώστε να χωράει. Κάτι τέτοιο συμβαίνει όταν ο χρήστης κάνει resize σε ένα παράθυρο. Αν δεν είναι ορισμένο το `GTK_SHRINK` είναι πολύ πιθανό σε μια τέτοια περίπτωση να μην εμφανίζονται τα widgets μέσα στον χώρο του παραθύρου μας. `GTK_EXPAND` Με αυτό τον τρόπο μπορούμε να αποδώσουμε στο table μας όλο τον χώρο που απομένει στο παράθυρο μετά τη δημιουργία του. Οι παραπάνω τιμές που μπορούν να πάρουν, είναι δυνατό να συνδυαστούν με το OR για να καλύψουμε περισσότερες από μια περιπτώσεις. `gint xpadding` Το γνωστό και πολλάκις εξηγημένο padding στον οριζόντιο άξονα `gint ypadding` `Οτι και το παραπάνω, αναφέρεται όμως στον κατακόρυφο άξονα Για όλους εσάς που όλα αυτά τα ορίσματα στην παραπάνω συνάρτηση σας φάνηκαν πολλά, υπάρχει και μια άλλη, που κάνει την ίδια (περίπου) δουλειά απλούστερα.
    void gtk_table_attach_defaults(GtkTable *table, GtkWidget *widget, gint left_attach,
                                   gint right_attach, gint top_attach, gint bottom_attach);
`Οπως παρατηρούμε, μόνο οι βασικές παραμέτροι περνάνε στη συνάρτηση. Ουσιαστικά δηλαδή, μόνο τα controls θέσης και μεγέθους. Οι παραμέτροι που δεν αναφέρονται, παίρνουν κάποιες προκαθορισμένες τιμές. Αυτές είναι οι πλέον χρησιμοποιούμενες, και συγκεκριμένα τα X και Y options γίνονται `GTK_FILL | GTK_EXPAND`, (ελπίζω να ξέρετε ότι το ``|'' είναι το OR) και στα X και Y padding δίδεται η τιμή 0. Για να καθορίσουμε το spacing ανάμεσα σε συγκεκριμένες γραμμές και στήλες ενός πίνακα, χρησιμοποιούμε τις παρακάτω συναρτήσεις:
         void gtk_table_set_row_spacing(GtkTable *table, gint row, gint spacing);
         void gtk_table_set_col_spacing(GtkTable *table, gint col, gint spacing);
όπου row ή col η γραμμή ή η στήλη στην οποία αναφερόμαστε, και spacing η απόσταση που θέλουμε να ορίσουμε σαν spacing. Για τις στήλες το spacing προστίθεται στα ΔΕΞΙΑ και για τις γραμμές ΚΑΤΩ. Είναι επίσης δυνατό να καθορίσουμε για ΟΛΕΣ τις στήλες ή γραμμές το spacing, χρησιμοποιώντας τις συναρτήσεις:
         void gtk_table_set_row_spacings(GtkTable *table, gint spacing);
         void gtk_table_set_col_spacings(GtkTable *table, gint spacing);
`Οπως πολύ καλά καταλάβατε, η τελευταία στήλη και η τελευταία σειρά δεν λαμβάνουν αυτή την τιμή, γιατί θα δημιουργούσε ένα κενό στα αριστερά και ένα κενό κάτω. Είναι φανερό ότι το να δουλεύει κανείς με tables είναι εύκολο. Εγώ προσωπικά δεν το προτιμώ, παρόλο που είναι βασικά η μόνη λύση στην περίπτωση που θέλουμε απόλυτα στοιχισμένα κουτάκια και κουμπάκια και widgets. Δοκιμάστε το πάντως, και πολλές φορές θα σας λύσει τα χέρια ### 5.3 Η συνέχεια Τον επόμενο μήνα θα συνεχίσουμε αυτό το άρθρο και θα ασχοληθούμε περισσότερο με τα widgets (buttons, radio/check/toggle buttons, text boxes, κ.λπ.) και τις ιδιότητές τους. Μέχρι τότε, πολλά φιλάκια. Προηγούμενο Περιεχόμενα