# Ραδιοπλήκτρα -RadioButton- (JavaScript)

Taryn Fox
jewelfox@fursona.net 2012
Μόνο ένα μπορεί να επιλεγεί τη φορά
Δημήτρης Σπίγγος
dmtrs32@gmail.com 2012, 2013

# Ράδιοπλήκτρο (RadioButton)

RadioButtons ονομάζονται κατά την παλιά μόδα ραδιοφώνων αυτοκινήτων, που είχαν κουμπιά για αλλαγή μεταξύ προκαθορισμένων καναλιών. Επειδή το ραδιόφωνο μπορούσε να συντονιστεί μόνο σε ένα σταθμό τη φορά, μόνο ένα κουμπί μπορούσε να πατηθεί τη φορά· αν πατούσατε ένα νέο, αυτό που ήταν ήδη πατημένο πεταγόταν πίσω. Έτσι δουλεύουν και αυτά τα κουμπιά.

Κάθε RadioButton χρειάζεται μία ετικέτα κειμένου και μια ομάδα. Μόνο ένα κουμπί σε μια ομάδα μπορεί να επιλεγεί τη φορά. Δεν ονομάζετε κάθε ομάδα· μόλις ρυθμίσατε νέα RadioButtons για να είναι τμήμα της ίδιας ομάδας ως μια υπάρχουσα. Εάν δημιουργείτε ένα νέο εκτός μιας ομάδας, δημιουργεί αυτόματα μια νέα ομάδα για να είναι μέρος του.

# Βιβλιοθήκες για εισαγωγή

#!/usr/bin/gjs

const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; const Lang = imports.lang;

Αυτές είναι οι βιβλιοθήκες που χρειαζόμαστε να εισάγουμε αυτήν την εφαρμογή για να εκτελεστεί. Να θυμόσαστε ότι η γραμμή που λέει στο GNOME ότι χρησιμοποιούμε Gjs χρειάζεται πάντοτε να πάει στην αρχή.

# Δημιουργία του παραθύρου εφαρμογής

const RadioButtonExample = new Lang.Class({ Name: 'RadioButton Example',

// Δημιουργία της εφαρμογής αυτής καθεαυτής _init: function() { this.application = new Gtk.Application({ application_id: 'org.example.jsradiobutton', flags: Gio.ApplicationFlags.FLAGS_NONE });

// Σύνδεση των σημάτων 'activate' και 'startup' με τις συναρτήσεις επανάκλησης this.application.connect('activate', Lang.bind(this, this._onActivate)); this.application.connect('startup', Lang.bind(this, this._onStartup)); },

// Η συνάρτηση επανάκλησης για το σήμα 'activate' παρουσιάζει παράθυρο όταν είναι ενεργή _onActivate: function() { this._window.present(); },

// Η συνάρτηση επανάκλησης για το σήμα 'startup' δομέί τη διεπαφή χρήστη _onStartup: function() { this._buildUI (); },

Όλος ο κώδικας για αυτό το παράδειγμα πηγαίνει στην κλάση RadioButtonExample. Ο παραπάνω κώδικας δημιουργεί μια Gtk.Application για να μπουν μέσα τα γραφικά συστατικά μας και τα παράθυρα.

// Δόμηση της διεπαφής χρήστη της εφαρμογής _buildUI: function() {

// Δημιουργία του παραθύρου της εφαρμογής this._window = new Gtk.ApplicationWindow({ application: this.application, window_position: Gtk.WindowPosition.CENTER, border_width: 20, title: "Travel Planning"});

Η συνάρτηση _buildUI είναι εκεί που βάζουμε όλον τον κώδικα για να δημιουργήσουμε τη διεπαφή χρήστη της εφαρμογής. Το πρώτο βήμα δημιουργεί ένα νέο Gtk.ApplicationWindow για να βάλουμε μέσα τα γραφικά συστατικά μας.

# Δημιουργία των ραδιοκουμπιών

// Δημιουργία μιας ετικέτας για την πρώτη ομάδα κουμπιών this._placeLabel = new Gtk.Label ({label: "Where would you like to travel to?"});

Χρησιμοποιούμε μια Gtk.Label για να ορίσουμε κάθε ομάδα RadioButtons ανεξάρτητα. Τίποτα δεν σας εμποδίζει να βάλετε τα RadioButtons από όλες τις διαφορετικές ομάδες όπου θέλετε, έτσι εάν θέλετε οι άλλοι να ξέρουν ποιο πηγαίνει μαζί, χρειαζόσαστε να οργανώσετε τα πράγματα ανάλογα.

// Δημιουργία τριών ραδιοπλήκτρων τριών διαφορετικών τρόπων this._place1 = new Gtk.RadioButton ({label: "The Beach"});

this._place2 = Gtk.RadioButton.new_from_widget (this._place1); this._place2.set_label ("The Moon");

this._place3 = Gtk.RadioButton.new_with_label_from_widget (this._place1, "Antarctica"); // this._place3.set_active (true);

Εδώ υπάρχουν τρεις διαφορετικοί τρόποι να δημιουργήσετε RadioButtons. Ο πρώτος είναι ο συνηθισμένος τρόπος, όπου δημιουργούμε ένα νέο Gtk.RadioButton και αποδίδουμε τις ιδιότητές του ταυτόχρονα. Ο δεύτερος και τρίτος χρησιμοποιούν συναρτήσεις που χειρίζονται αυτόματα μερικές από τις ιδιότητες· το new_from_widget παίρνει ένα μοναδικό όρισμα, το RadioButton στο οποίο θέλετε να βάλετε αυτό το νέο στην ίδια ομάδα. Εν τω μεταξύ, το new_with_label_from_widget το παίρνει καθώς και την ετικέτα του RadioButton ταυτόχρονα.

Το πρώτο RadioButton σε μια ομάδα είναι αυτό που επιλέγεται από προεπιλογή. Δοκιμάστε την αποσχολίαση της τελευταίας γραμμής σε αυτό το δείγμα κώδικα για να δείτε πώς μπορείτε να ρυθμίσετε ένα διαφορετικό να είναι η προεπιλογή.

// Δημιουργία μιας ετικέτας για τη δεύτερη ομάδα κουμπιών this._thingLabel = new Gtk.Label ({label: "And what would you like to bring?" });

// Δημιουργία τριών επιπλέον ραδιοπλήκτρων this._thing1 = new Gtk.RadioButton ({label: "Penguins" }); this._thing2 = new Gtk.RadioButton ({label: "Sunscreen", group: this._thing1 }); this._thing3 = new Gtk.RadioButton ({label: "A spacesuit", group: this._thing1 });

Εδώ δημιουργούμε την ετικέτα για τη δεύτερη ομάδα κουμπιών και έπειτα τα δημιουργούμε όλα με τον ίδιο τρόπο.

# Δημιουργία της υπόλοιπης διεπαφής χρήστη

// Δημιουργία ενός πλήκτρου παρακαταθήκης ΕΝΤΑΞΕΙ this._okButton = new Gtk.Button ({ label: 'gtk-ok', use_stock: 'true', halign: Gtk.Align.END });

// Σύνδεση του κουμπιού με τη συνάρτηση που χειρίζεται το πάτημά του this._okButton.connect ('clicked', Lang.bind (this, this._okClicked));

Αυτός ο κώδικας δημιουργεί ένα Gtk.Button και το συνδέει με μια συνάρτηση που θα εμφανίσει στους άλλους ένα χαζό μήνυμα όταν πατήσουν εντάξει, ανάλογα με τα επιλεγμένα RadioButtons.

Για να βεβαιωθείτε ότι η ετικέτα του κουμπιού "OK" εμφανίζεται κατάλληλα σε κάθε γλώσσα στην οποία μεταφράζεται το GNOME, να θυμάστε να χρησιμοποιήσετε έναν από τους τύπους κουμπιών παρακαταθήκης του Gtk.

// Δημιουρία ενός πλέγματος για τοποθέτηση των στοιχείων "place" μέσα this._places = new Gtk.Grid ();

// Προσάρτηση των στοιχείων "place" στο πλέγμα this._places.attach (this._placeLabel, 0, 0, 1, 1); this._places.attach (this._place1, 0, 1, 1, 1); this._places.attach (this._place2, 0, 2, 1, 1); this._places.attach (this._place3, 0, 3, 1, 1);

// Δημιουργία ενός πλέγματος για τοποθέτηση των στοιχείων "thing" μέσα this._things = new Gtk.Grid ({ margin_top: 50 });

// Προσάρτηση των στοιχείων "thing" στο πλέγμα this._things.attach (this._thingLabel, 0, 0, 1, 1); this._things.attach (this._thing1, 0, 1, 1, 1); this._things.attach (this._thing2, 0, 2, 1, 1); this._things.attach (this._thing3, 0, 3, 1, 1);

// Δημιουργία ενός πλέγματος για τοποθέτηση όλων μέσα this._grid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER, margin_left: 40, margin_right: 50 });

// Προσάρτηση όλων στο πλέγμα this._grid.attach (this._places, 0, 0, 1, 1); this._grid.attach (this._things, 0, 1, 1, 1); this._grid.attach (this._okButton, 0, 2, 1, 1);

// Προσάρτηση του πλέγματος στο παράθυρο this._window.add (this._grid);

Χρησιμοποιούμε ένα ανεξάρτητο Gtk.Grid για να οργανώσουμε κάθε ομάδα ραδιοπλήκτρων. Με αυτό τον τρόπο μπορούμε να αλλάξουμε τη διάταξη με λιγότερη αναστάτωση αργότερα. Το δεύτερο πλέγμα έχει ένα περιθώριο στην κορυφή, για οπτική διάκριση των δύο συνόλων επιλογών.

Αφού τα οργανώσουμε, τα βάζουμε σε ένα τρίτο, κύριο πλέγμα, μαζί με το κουμπί εντάξει. Έπειτα το προσαρτούμε στο παράθυρο.

// Εμφάνιση του παραθύρου και όλων των θυγατρικών γραφικών συστατικών this._window.show_all(); },

Τελικά, λέμε στο παράθυρο και σε κάθε τι που είναι μέσα του να γίνει ορατό όταν τρέχει η εφαρμογή.

# Η συνάρτηση που χειρίζεται την επιλογή σας

_okClicked: function () {

// Δημιουργία ενός αναδυόμενου που εμφανίζει ένα χαζό μήνυμα this._travel = new Gtk.MessageDialog ({ transient_for: this._window, modal: true, message_type: Gtk.MessageType.OTHER, buttons: Gtk.ButtonsType.OK, text: this._messageText() });

// Εμφάνιση του αναδυόμενου this._travel.show();

// Σύνδεση του κουμπιού ΕΝΤΑΞΕΙ με τη συνάρτηση που κλείνει το αναδυόμενο this._travel.connect ("response", Lang.bind (this, this._clearTravelPopUp));

},

Όταν πατάτε εντάξει, ένας Gtk.MessageDialog εμφανίζεται. Αυτή η συνάρτηση δημιουργεί και εμφανίζει το αναδυόμενο παράθυρο, έπειτα συνδέει το κουμπί της εντάξει με τη συνάρτηση που το κλείνει. Τι κείμενο εμφανίζεται στο αναδυόμενο εξαρτάται από τη συνάρτηση _messageText(), που επιστρέφει μια διαφορετική τιμή ανάλογα με το σύνολο επιλογών που διαλέξατε.

_messageText: function() {

// Δημιουργία ενός χαζού μηνύματος για το αναδυόμενο ανάλογα με το τι διαλέξατε var stringMessage = "";

if (this._place1.get_active()) {

if (this._thing1.get_active()) stringMessage = "Penguins love the beach, too!";

else if (this._thing2.get_active()) stringMessage = "Make sure to put on that sunscreen!";

else stringMessage = "Are you going to the beach in space?";

}

else if (this._place2.get_active()) {

if (this._thing1.get_active()) stringMessage = "The penguins will take over the moon!";

else if (this._thing2.get_active()) stringMessage = "A lack of sunscreen will be the least of your problems!";

else stringMessage = "You'll probably want a spaceship, too!"; }

else if (this._place3.get_active()) {

if (this._thing1.get_active()) stringMessage = "The penguins will be happy to be back home!";

else if (this._thing2.get_active()) stringMessage = "Antarctic sunbathing may be hazardous to your health!";

else stringMessage = "Try bringing a parka instead!"; }

return stringMessage;

},

Η μέθοδος get_active() λέει πώς μπορούμε να πούμε ποιο RadioButton πατιέται. Αυτή η συνάρτηση επιστρέφει ένα διαφορετικό χαζό μήνυμα ανάλογα με ποιο σύνολο κουμπιών πατήθηκε. Η επιστρεφόμενη τιμή χρησιμοποιείται ως ιδιότητα κειμένου του MessageDialog.

_clearTravelPopUp: function () {

this._travel.destroy();

}

});

Αυτή η συνάρτηση καλείται όταν το κουμπί εντάξει του MessageDialog πατιέται. Κάνει απλά το αναδυόμενο να φύγει.

// Εκτέλεση της εφαρμογής let app = new RadioButtonExample (); app.application.run (ARGV);

Τελικά, δημιουργούμε ένα νέο παράδειγμα της τελειωμένης κλάσης RadioButtonExample και εκτελούμε την εφαρμογή.

# Δείγμα πλήρους κώδικα

#!/usr/bin/gjs

const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; const Lang = imports.lang;

const RadioButtonExample = new Lang.Class({ Name: 'RadioButton Example',

// Δημιουργία της εφαρμογής αυτής καθεαυτής _init: function() { this.application = new Gtk.Application({ application_id: 'org.example.jsradiobutton', flags: Gio.ApplicationFlags.FLAGS_NONE });

// Σύνδεση των σημάτων 'activate' και 'startup' με τις συναρτήσεις επανάκλησης this.application.connect('activate', Lang.bind(this, this._onActivate)); this.application.connect('startup', Lang.bind(this, this._onStartup)); },

// Η συνάρτηση επανάκλησης για το σήμα 'activate' παρουσιάζει ένα παράθυρο όταν είναι ενεργή _onActivate: function() { this._window.present(); },

// Η συνάρτηση επανάκλησης για το σήμα 'startup' δομεί τη διεπαφή χρήστη _onStartup: function() { this._buildUI (); },

// Δόμηση της διεπαφής χρήστη της εφαρμογής _buildUI: function() {

// Δημιουργία του παραθύρου της εφαρμογής this._window = new Gtk.ApplicationWindow({ application: this.application, window_position: Gtk.WindowPosition.CENTER, border_width: 20, title: "Travel Planning"});

// Δημιουργία μιας ετικέτας για την πρώτη ομάδα των κουμπιών this._placeLabel = new Gtk.Label ({label: "Where would you like to travel to?"});

// Δημιουργία τριών ραδιοπλήκτων τριών διαφορετικών δρόμων this._place1 = new Gtk.RadioButton ({label: "The Beach"});

this._place2 = Gtk.RadioButton.new_from_widget (this._place1); this._place2.set_label ("The Moon");

this._place3 = Gtk.RadioButton.new_with_label_from_widget (this._place1, "Antarctica"); // this._place3.set_active (true);

// Δημιουργία μιας ετικέτας για τη δεύτερη ομάδα κουμπιών this._thingLabel = new Gtk.Label ({label: "And what would you like to bring?" });

// Δημιουργία τριών πρόσθετων ραδιοπλήκτρων this._thing1 = new Gtk.RadioButton ({label: "Penguins" }); this._thing2 = new Gtk.RadioButton ({label: "Sunscreen", group: this._thing1 }); this._thing3 = new Gtk.RadioButton ({label: "A spacesuit", group: this._thing1 });

// Δημιουργία ενός πλήκτρου παρακαταθήκης ΕΝΤΑΞΕΙ this._okButton = new Gtk.Button ({ label: 'gtk-ok', use_stock: 'true', halign: Gtk.Align.END });

// Σύνδεση του πλήκτρου με τη συνάρτηση που χειρίζεται το πάτημά του this._okButton.connect ('clicked', Lang.bind (this, this._okClicked));

// Δημιουργία ενός πλέγματος για την τοποθέτηση των στοιχείων "place" μέσα this._places = new Gtk.Grid ();

// Προσάρτηση των στοιχείων "place" στο πλέγμα this._places.attach (this._placeLabel, 0, 0, 1, 1); this._places.attach (this._place1, 0, 1, 1, 1); this._places.attach (this._place2, 0, 2, 1, 1); this._places.attach (this._place3, 0, 3, 1, 1);

// Δημιουργία ενός πλέγματος για τοποθέτηση των στοιχείων "thing" μέσα this._things = new Gtk.Grid ({ margin_top: 50 });

// Προσάρτηση των στοιχείων "thing" στο πλέγμα this._things.attach (this._thingLabel, 0, 0, 1, 1); this._things.attach (this._thing1, 0, 1, 1, 1); this._things.attach (this._thing2, 0, 2, 1, 1); this._things.attach (this._thing3, 0, 3, 1, 1);

// Δημιουργία ενός πλέγματος για να μπουν όλα μέσα this._grid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER, margin_left: 40, margin_right: 50 });

// Προσάρτηση όλων στο πλέγμα this._grid.attach (this._places, 0, 0, 1, 1); this._grid.attach (this._things, 0, 1, 1, 1); this._grid.attach (this._okButton, 0, 2, 1, 1);

// Προσθήκη του πλέγματος στο παράθυρο this._window.add (this._grid);

// Εμφάνιση των παραθύρων και όλων των θυγατρικών γραφικών συστατικών this._window.show_all(); },

_okClicked: function () {

// Δημιουργία ενός αναδυόμενου που εμφανίζει ένα χαζό μήνυμα this._travel = new Gtk.MessageDialog ({ transient_for: this._window, modal: true, message_type: Gtk.MessageType.OTHER, buttons: Gtk.ButtonsType.OK, text: this._messageText() });

// Εμφάνιση του αναδυόμενου this._travel.show();

// Σύνδεση του πλήκτρου ΕΝΤΑΞΕΙ στη συνάρτηση που κλείνει το αναδυόμενο this._travel.connect ("response", Lang.bind (this, this._clearTravelPopUp));

},

_messageText: function() {

// Δημιουργία ενός χαζού μηνύματος για το αναδυόμενο ανάλογα με το τι επιλέξατε var stringMessage = "";

if (this._place1.get_active()) {

if (this._thing1.get_active()) stringMessage = "Penguins love the beach, too!";

else if (this._thing2.get_active()) stringMessage = "Make sure to put on that sunscreen!";

else stringMessage = "Are you going to the beach in space?";

}

else if (this._place2.get_active()) {

if (this._thing1.get_active()) stringMessage = "The penguins will take over the moon!";

else if (this._thing2.get_active()) stringMessage = "A lack of sunscreen will be the least of your problems!";

else stringMessage = "You'll probably want a spaceship, too!"; }

else if (this._place3.get_active()) {

if (this._thing1.get_active()) stringMessage = "The penguins will be happy to be back home!";

else if (this._thing2.get_active()) stringMessage = "Antarctic sunbathing may be hazardous to your health!";

else stringMessage = "Try bringing a parka instead!"; }

return stringMessage;

},

_clearTravelPopUp: function () {

this._travel.destroy();

}

});

// Εκτέλεση της εφαρμογής let app = new RadioButtonExample (); app.application.run (ARGV);

# Τεκμηρίωση σε βάθος

Gtk.Application

Gtk.ApplicationWindow

Gtk.Button

Gtk.Grid

Gtk.Label

Gtk.RadioButton