Rust로 계산기를 만들어보자! - (UI 만들기)

apriljade·2022년 5월 23일
0

시작


지난번에 필요 라이브러리 설치 및 gtk4 예제를 한번 실행했었는데요! 이번에 해보려는 것은 버튼 ui추가하기 입니다!

버튼 UI 추가하기


Grid Layout

우리가 흔히 볼 수 있는 계산기의 UI는 숫자패드와 연산 버튼의 조합이 열과 행을 이루고 있습니다. 열과 행으로 이뤄지는 레이아웃은 Table이나 Grid가 있는데요, gtk에 내장되어있는 Grid Layout을 활용하여 버튼들을 만들어주겠습니다!

GObject

gtk의 UI 요소들은 GObject를 기반으로 구현되어 있습니다. 해당 구조에 대해 간단히 말씀드리면 ApplicationWindow가 우리가 만들 앱의 최상위 UI요소인데, 여기에 우리가 필요한 버튼이나 리스트를 부착해주는 식입니다. 곧바로 코드에서 UI생성과 배치를 할 수 있고 다른 방법으로는 Composite Templates라는 방법도 있는데, 우선 코드로 전부 구성해보고 추후에 Composite Templates로 리팩터링을 해보겠습니다!

Grid Layout 생성하고 부착하기!

GObject는 Builder Pattern으로 생성할 수 있습니다. 아래의 코드처럼 생성 및 부착을 합니다.

use gtk4 as gtk;
use glib::clone;
use gtk::glib;
use gtk::prelude::*;

fn main() {
    let application = gtk::Application::new(
        Some("com.github.aprilJade.rs-calculator"),
        Default::default(),
    );

    application.connect_activate(build_ui);
    application.run();
}

fn build_ui(application: &gtk::Application) {
    let window = gtk::ApplicationWindow::new(application);
    window.set_title(Some("Calculator"));

    let grid = gtk::Grid::builder()
        .margin_start(6)
        .margin_end(6)
        .margin_top(80)
        .margin_bottom(6)
        .halign(gtk::Align::Center)
        .valign(gtk::Align::Center)
        .row_spacing(0)
        .column_spacing(0)
        .can_focus(false)
        .build();
    window.set_child(Some(&grid));

    window.show();
}

최상위 UI 요소인 ApplicationWindow를 먼저 생성해주고 Grid를 builder()를 이용하여 생성해줍니다. 각각의 요소가 어떤 것을 의미하는지는 공식 API 문서를 참조해주세요!

Button 생성 및 Grid에 배치하기

Grid는 Layout입니다. 그 안에 요소들을 배치하는 일련의 규칙을 의미하는데, 쉽게 생각하면 행과 열로 이루어진 표입니다. 여기에 Button UI를 부착해주면 우리가 원하는 Button들을 우리가 원하는 대로 정렬해줄 수 있습니다.
아래의 코드는 버튼을 Grid에 부착하는 코드입니다.

use gtk4 as gtk;
use glib::clone;
use gtk::glib;
use gtk::prelude::*;

fn main() {
    let application = gtk::Application::new(
        Some("com.github.aprilJade.rs-calculator"),
        Default::default(),
    );

    application.connect_activate(build_ui);
    application.run();
}

fn build_ui(application: &gtk::Application) {
    // Create a new window, set its title and default size
    let window = gtk::ApplicationWindow::new(application);
    window.set_title(Some("Calculator"));

    // Here we construct the grid that is going contain our buttons.
    let grid = gtk::Grid::builder()
        .margin_start(6)
        .margin_end(6)
        .margin_top(80)
        .margin_bottom(6)
        .halign(gtk::Align::Center)
        .valign(gtk::Align::Center)
        .row_spacing(0)
        .column_spacing(0)
        .can_focus(false)
        .build();
    window.set_child(Some(&grid));

    let button = gtk::Button::with_label("0");

    grid.attach(&button, 0, 0, 1, 1);

    window.show();
}

button을 만들어내고 grid.attach 함수를 사용하여 Grid에 버튼을 추가합니다. attach함수는 이런 매개변수를 받습니다.

attach(&button_ref, col, row, width, height)

저는 계산기에 초기화, 부호, 나머지, 나눗셈, 곱셈, 뺄셈, 덧셈, 등호, 소숫점, 숫자버튼을 만들고 배치해보려 합니다. 버튼하나 만들었던 걸 똑같이 만들어주면됩니다.

use gtk4 as gtk;
use glib::clone;
use gtk::glib;
use gtk::prelude::*;

fn main() {
    let application = gtk::Application::new(
        Some("com.github.aprilJade.rs-calculator"),
        Default::default(),
    );

    application.connect_activate(build_ui);
    application.run();
}

fn build_ui(application: &gtk::Application) {
    // Create a new window, set its title and default size
    let window = gtk::ApplicationWindow::new(application);
    window.set_title(Some("Calculator"));

    // Here we construct the grid that is going contain our buttons.
    let grid = gtk::Grid::builder()
        .margin_start(6)
        .margin_end(6)
        .margin_top(80)
        .margin_bottom(6)
        .halign(gtk::Align::Center)
        .valign(gtk::Align::Center)
        .row_spacing(0)
        .column_spacing(0)
        .can_focus(false)
        .build();
    window.set_child(Some(&grid));

    let btn_len = 1;
    let button_0 = gtk::Button::with_label("0");
    let button_1 = gtk::Button::with_label("1");
    let button_2 = gtk::Button::with_label("2");
    let button_3 = gtk::Button::with_label("3");
    let button_4 = gtk::Button::with_label("4");
    let button_5 = gtk::Button::with_label("5");
    let button_6 = gtk::Button::with_label("6");
    let button_7 = gtk::Button::with_label("7");
    let button_8 = gtk::Button::with_label("8");
    let button_9 = gtk::Button::with_label("9");
    let button_cancel = gtk::Button::with_label("AC");
    let button_sign = gtk::Button::with_label("+/-");
    let button_modular = gtk::Button::with_label("%");
    let button_divider = gtk::Button::with_label("÷");
    let button_mutiplier = gtk::Button::with_label("x");
    let button_minus = gtk::Button::with_label("-");
    let button_plus = gtk::Button::with_label("+");
    let button_equal = gtk::Button::with_label("=");
    let button_point = gtk::Button::with_label(".");

	// 0번째 행
    grid.attach(&button_cancel, 0, 0, btn_len, btn_len);
    grid.attach(&button_sign, 1, 0, btn_len, btn_len);
    grid.attach(&button_modular, 2, 0, btn_len, btn_len);
    grid.attach(&button_divider, 3, 0, btn_len, btn_len);
    
    // 1번째 행
    grid.attach(&button_7, 0, 1, btn_len, btn_len);
    grid.attach(&button_8, 1, 1, btn_len, btn_len);
    grid.attach(&button_9, 2, 1, btn_len, btn_len);
    grid.attach(&button_mutiplier, 3, 1, btn_len, btn_len);
    
    // 2번째 행
    grid.attach(&button_4, 0, 2, btn_len, btn_len);
    grid.attach(&button_5, 1, 2, btn_len, btn_len);
    grid.attach(&button_6, 2, 2, btn_len, btn_len);
    grid.attach(&button_minus, 3, 2, btn_len, btn_len);
	
    // 3번째 행
    grid.attach(&button_1, 0, 3, btn_len, btn_len);
    grid.attach(&button_2, 1, 3, btn_len, btn_len);
    grid.attach(&button_3, 2, 3, btn_len, btn_len);
    grid.attach(&button_plus, 3, 3, btn_len, btn_len);
    
    // 4번째 행
    grid.attach(&button_0, 0, 4, btn_len * 2, btn_len);
    grid.attach(&button_point, 2, 4, btn_len, btn_len);
    grid.attach(&button_equal, 3, 4, btn_len, btn_len);

    window.show();
}

실행시켜보면...

귀여운 친구가 나타납니다!
이제 숙제로 텍스트를 표시해줄 공간을 부착해봅니다. Entry라는 친구가 있습니다. 그 친구를 Grid위에 붙여주면 되겠지요? 혹은 margin값을 없애주고 버튼의 행번호를 하나씩 증가시킨 후 0번째 행에 Entry를 부착해줘도 됩니다! 편하신 방법으로 진행해주세요!

마치며


0번째 글만 제대로 따라하셨다면 이 다음부터는 그리 어렵지 않습니다. 공식문서를 참고하여 차근차근 따라하시면됩니다!! 공식문서를 찾아내는 것도 필요한 능력이기에 이곳에 링크를 남겨두진 않겠습니다!

0개의 댓글