Magaz, The Greek Linux Magazine
Magaz Logo

Προηγούμενο  Περιεχόμενα

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, κ.λπ.) και τις ιδιότητές τους. Μέχρι τότε, πολλά φιλάκια.

Προηγούμενο  Περιεχόμενα


Valid HTML 4.01!   Valid CSS!