# RadioButton (JavaScript)

Taryn Fox
jewelfox@fursona.net 2012
한번에 하나만 선택할 수 있습니다
조성호
shcho@gnome.org 2017-2019.

# RadioButton

RadioButton 이름은 미리 설정해둔 채널을 전환할 때 사용하는 단추의 모양새 동작에 착안하여 구식 자동차 라디오에서 왔습니다. 라디오 채널 설정은 한번에 하나만 할 수 있기 때문에, 오직 하나의 단추만 눌립니다. 새 단추를 누르면 먼저 눌려있던 단추는 도로 튀어나옵니다. 이게 바로 라디오 단추가 동작하는 방식입니다.

각 라디오 단추는 텍스트 레이블을 넣고 그룹으로 묶어야합니다. 그룹에서는 한번에 하나의 단추만 선택할 수 있습니다. 각 그룹에 이름을 달 수는 없습니다. 새 RadioButton은 기존의 단추와 마찬가지로 동일한 그룹의 일부로 설정합니다. 그룹의 밖에 새 단추를 넣으면, 이 단추는 자동으로 새 그룹의 일부가 됩니다.

# 가져올 라이브러리

#!/usr/bin/gjs

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

이 프로그램을 실행할 때 가져올 라이브러리입니다. 시작 부분에 항상 gjs가 필요함을 알리는 줄을 작성해야 함을 기억하십시오.

# 프로그램 창 만들기

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

// Create the application itself _init: function() { this.application = new Gtk.Application({ application_id: 'org.example.jsradiobutton', flags: Gio.ApplicationFlags.FLAGS_NONE });

// Connect 'activate' and 'startup' signals to the callback functions this.application.connect('activate', Lang.bind(this, this._onActivate)); this.application.connect('startup', Lang.bind(this, this._onStartup)); },

// Callback function for 'activate' signal presents window when active _onActivate: function() { this._window.present(); },

// Callback function for 'startup' signal builds the UI _onStartup: function() { this._buildUI (); },

이 예제의 모든 코드는 RadioButtonExample 클래스에 들어갑니다. 위 코드는 위젯과 창이 들어가는 Gtk.Application을 만듭니다.

// Build the application's UI _buildUI: function() {

// Create the application window this._window = new Gtk.ApplicationWindow({ application: this.application, window_position: Gtk.WindowPosition.CENTER, border_width: 20, title: "Travel Planning"});

_buildUI 함수는 프로그램 사용자 인터페이스를 만드는 모든 코드를 넣는 곳입니다. 첫 단계에서는 모든 위젯을 우겨넣을 새 Gtk.ApplicationWindow를 만듭니다.

# RadioButton 만들기

// Create a label for the first group of buttons this._placeLabel = new Gtk.Label ({label: "Where would you like to travel to?"});

그룹에 있는 각 RadioButton 부분 부분마다 Gtk.Label을 설정 용도로 사용합니다. 원하는 어디든 모든 다른 그룹에 RadioButton을 넣지 못하게 하진 않습니다. 따라서 사용자가 어떤 단추를 한 묶음으로 두었는지 알 수 있게 하려면 묶음별로 정리해야합니다.

// Create three radio buttons three different ways 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);

RadioButton을 만드는 방법은 세가지가 있습니다. 첫번째는 Gtk.RadioButton을 새로 만들고 속성을 동시에 지정하는 일반적인 방법, 두번째와 세번째는 일부 속성 값을 자동으로 처리하는 함수를 사용하는 방법입니다. new_from_widget은 동일한 그룹에 새 단추를 넣으려고 할 때 넣을 RadioButton 단일 인자를 취하지만, new_with_label_from_widget은 RadioButton 레이블을 함께 취합니다.

그룹의 처음 RadioButton은 기본으로 선택하는 항목입니다. 이 예제 코드의 마지막 줄 주석 표시를 제거해보셔서 다른 항목을 어떻게 기본으로 선택할 수 있는지 확인해보십시오.

// Create a label for the second group of buttons this._thingLabel = new Gtk.Label ({label: "And what would you like to bring?" });

// Create three more radio buttons 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 });

여기서 그룹의 두번째 단추에 레이블을 만들어넣고, 나머지 단추에 대해서도 동일한 방식으로 만듭니다.

# 사용자 인터페이스 나머지 부분 만들기

// Create a stock OK button this._okButton = new Gtk.Button ({ label: 'gtk-ok', use_stock: 'true', halign: Gtk.Align.END });

// Connect the button to the function which handles clicking it this._okButton.connect ('clicked', Lang.bind (this, this._okClicked));

이 코드는 Gtk.Button을 만들고 함수에 바인딩하여, 사용자가 확인을 누르면 어떤 RadioButton을 선택했느냐에 따라 유치한 메시지를 보여줍니다.

단추의 "확인" 레이블을 그놈에서 번역한대로 각 언어로 올바르게 나타나게 하려면, GTK 스톡 단추 형식 활용 방식을 기억에서 되살려보십시오.

// Create a grid to put the "place" items in this._places = new Gtk.Grid ();

// Attach the "place" items to the grid 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);

// Create a grid to put the "thing" items in this._things = new Gtk.Grid ({ margin_top: 50 });

// Attach the "thing" items to the grid 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);

// Create a grid to put everything in this._grid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER, margin_left: 40, margin_right: 50 });

// Attach everything to the grid 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);

// Add the grid to the window this._window.add (this._grid);

라디오 단추를 각 그룹으로 묶는 용도로 Gtk.Grid 를 따로 사용합니다. 이 방식대로라면 나중에 덜 난리나는 방식으로 배치를 바꿀 수 있습니다. 두번째 그리드는 상단에 여백을 두었는데 두 선택 그룹을 눈으로 보기에 따로 나뉘어 보기에 한 부분입니다.

이렇게 정돈한 다음에는 세번째로 마스터 그리드를 넣고, 그 안에 확인 단추를 넣습니다. 이 과정이 끝나면 마스터 그리드를 창에 넣습니다.

// Show the window and all child widgets this._window.show_all(); },

마지막으로 프로그램을 실행할 때 창과 창에 있는 모든 요소를 나타내라고 하겠습니다.

# 선택을 처리하는 함수

_okClicked: function () {

// Create a popup that shows a silly message this._travel = new Gtk.MessageDialog ({ transient_for: this._window, modal: true, message_type: Gtk.MessageType.OTHER, buttons: Gtk.ButtonsType.OK, text: this._messageText() });

// Show the popup this._travel.show();

// Bind the OK button to the function that closes the popup this._travel.connect ("response", Lang.bind (this, this._clearTravelPopUp));

},

확인을 누르면 Gtk.MessageDialog가 나타납니다. 이 함수는 팝업 창을 만들어 띄운 후 창을 닫는 확인 단추에 함수를 연결합니다. 여러분이 선택한 옵션 설정에 따라 다른 값을 반환하는 _messageText() 함수에서 반환하는 값에 따라 팝업 창에 나타나는 텍스트가 달라집니다.

_messageText: function() {

// Create a silly message for the popup depending on what you selected 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의 확인 단추를 누를 때 호출합니다.

// Run the application let app = new RadioButtonExample (); app.application.run (ARGV);

마지막으로, 마무리 지은 RadioButtonExample 클래스의 새 인스턴스를 만들고 프로그램 실행을 설정하겠습니다.

# 완전한 코드 예제

#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';

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

class RadioButtonExample {

// Create the application itself constructor() { this.application = new Gtk.Application({ application_id: 'org.example.jsradiobutton', flags: Gio.ApplicationFlags.FLAGS_NONE });

// Connect 'activate' and 'startup' signals to the callback functions this.application.connect('activate', this._onActivate.bind(this)); this.application.connect('startup', this._onStartup.bind(this)); }

// Callback function for 'activate' signal presents window when active _onActivate() { this._window.present(); }

// Callback function for 'startup' signal builds the UI _onStartup() { this._buildUI(); }

// Build the application's UI _buildUI() {

// Create the application window this._window = new Gtk.ApplicationWindow({ application: this.application, window_position: Gtk.WindowPosition.CENTER, border_width: 20, title: "Travel Planning"});

// Create a label for the first group of buttons this._placeLabel = new Gtk.Label ({label: "Where would you like to travel to?"});

// Create three radio buttons three different ways 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);

// Create a label for the second group of buttons this._thingLabel = new Gtk.Label ({label: "And what would you like to bring?" });

// Create three more radio buttons 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 });

// Create a stock OK button this._okButton = new Gtk.Button ({ label: 'gtk-ok', use_stock: 'true', halign: Gtk.Align.END });

// Connect the button to the function which handles clicking it this._okButton.connect ('clicked', this._okClicked.bind(this));

// Create a grid to put the "place" items in this._places = new Gtk.Grid ();

// Attach the "place" items to the grid 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);

// Create a grid to put the "thing" items in this._things = new Gtk.Grid ({ margin_top: 50 });

// Attach the "thing" items to the grid 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);

// Create a grid to put everything in this._grid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER, margin_left: 40, margin_right: 50 });

// Attach everything to the grid 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);

// Add the grid to the window this._window.add (this._grid);

// Show the window and all child widgets this._window.show_all(); }

_okClicked() {

// Create a popup that shows a silly message this._travel = new Gtk.MessageDialog ({ transient_for: this._window, modal: true, message_type: Gtk.MessageType.OTHER, buttons: Gtk.ButtonsType.OK, text: this._messageText() });

// Show the popup this._travel.show();

// Bind the OK button to the function that closes the popup this._travel.connect ("response", this._clearTravelPopUp.bind(this));

}

_messageText() {

// Create a silly message for the popup depending on what you selected 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() { this._travel.destroy(); } };

// Run the application let app = new RadioButtonExample (); app.application.run (ARGV);

# 자세한 문서

Gtk.Application

Gtk.ApplicationWindow

Gtk.Button

Gtk.Grid

Gtk.Label

Gtk.RadioButton