Σύνδεση χειριστών σημάτων

Οι κλάσεις γραφικών συστατικών gtkmm έχουν μεθόδους στοιχείων πρόσβασης σήματος, όπως Gtk::Button::signal_clicked(), που επιτρέπουν να συνδεθείτε με τον χειριστή σήματός σας. Χάρη στην ευελιξία της libsigc++, την βιβλιοθήκη επανάκλησης που χρησιμοποιείται από την gtkmm, ο χειριστής σήματος μπορεί να είναι σχεδόν κάθε είδος συνάρτησης, αλλά προφανώς θα θέλετε να χρησιμοποιήσετε μια μέθοδο κλάσεων. Μεταξύ των κωδικοποιητών C της GTK+, αυτοί οι χειριστές σήματος ονομάζονται συχνά επανακλήσεις.

Ιδού ένα παράδειγμα ενός χειριστή σήματος που συνδέθηκε σε ένα σήμα:

#include <gtkmm/button.h>

void on_button_clicked()
{
    std::cout << "Hello World" << std::endl;
}

main()
{
    Gtk::Button button("Hello World");
    button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked));
}

Υπάρχουν μάλλον πολλά να σκεφτείτε για αυτόν τον (μη λειτουργικό) κώδικα. Πρώτα ας αναγνωρίσουμε τα εμπλεκόμενα μέρη:

  • Ο χειριστής σήματος είναι on_button_clicked().
  • Το συνδέουμε στο αντικείμενο Gtk::Button που λέγεται button.
  • Όταν το πλήκτρο εκπέμπει το σήμα του clicked, θα κληθεί η on_button_clicked() will be called.

Τώρα ας κοιτάξουμε στη σύνδεση ξανά:

    ...
    button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked));
    ...

Σημειώστε ότι δεν περάσαμε έναν δείκτη στην on_button_clicked() άμεσα από τη μέθοδο connect() του σήματος. Αντίθετα, καλούμε sigc::ptr_fun() και περνάμε το αποτέλεσμα στην connect().

Η sigc::ptr_fun() δημιουργεί μια sigc::slot. Μια υποδοχή είναι ένα αντικείμενο που φαίνεται και αισθάνεται όπως μια συνάρτηση, αλλά στην πραγματικότητα είναι ένα αντικείμενο. Αυτά είναι επίσης γνωστά ως αντικείμενα συνάρτησης, ή functors. Η sigc::ptr_fun() δημιουργεί μια υποδοχή για μια αυτόνομη συνάρτηση ή στατική μέθοδο. Η sigc::mem_fun() δημιουργεί μια υποδοχή για μια μέθοδο μέλους ενός ιδιαίτερου στιγμιότυπου.

Ιδού ένα ελαφρώς μεγαλύτερο παράδειγμα υποδοχών σε δράση:

void on_button_clicked();

class some_class
{
    void on_button_clicked();
};

some_class some_object;

main()
{
    Gtk::Button button;
    button.signal_clicked().connect( sigc::ptr_fun(&on_button_clicked) );
    button.signal_clicked().connect( sigc::mem_fun(some_object, &some_class::on_button_clicked) );
}

Η πρώτη κλήση στην connect() είναι ακριβώς όπως αυτή που είδαμε την τελευταία φορά· τίποτα νέο εδώ.

Το επόμενο είναι πιο ενδιαφέρον. Η sigc::mem_fun() καλείται με δύο ορίσματα. Το πρώτο όρισμα είναι some_object, που είναι το αντικείμενο που η νέα μας υποδοχή θα δείχνει. Το δεύτερο όρισμα είναι ένας δείκτης σε μια από τις μεθόδους του. Αυτή η συγκεκριμένη έκδοση της sigc::mem_fun() δημιουργεί μια υποδοχή που, όταν "κληθεί", θα καλέσει τη μέθοδο στην οποία δείχνει του συγκεκριμένου αντικειμένου, σε αυτήν την περίπτωση στην some_object.on_button_clicked().

Ένα άλλο πράγμα που πρέπει να σημειώσετε για αυτό το παράδειγμα είναι ότι κάναμε την κλήση στην connect() δυο φορές για το ίδιο αντικείμενο σήματος. Αυτό είναι ολότελα θαυμάσιο - όταν το πλήκτρο πατιέται, και οι δύο χειριστές σήματος θα κληθούν.

Μόλις σας είπαμε ότι το σήμα clicked του πλήκτρου αναμένει να καλέσει μια μέθοδο χωρίς ορίσματα. Όλα τα σήματα έχουν απαιτήσεις όπως αυτό - δεν μπορείτε να αγκιστρώσετε μια συνάρτηση με δύο ορίσματα σε ένα σήμα που δεν περιμένει κανένα (εκτός και χρησιμοποιείτε έναν προσαρμογέα, όπως sigc::bind(), φυσικά). Συνεπώς, είναι σημαντικό να ξέρετε ποιος τύπος χειριστή σήματος θα αναμένεται για να συνδεθεί με το δοσμένο σήμα.