Создание структуры пользовательского интерфейса (UI)
Используя структуру предыдущей главы в качестве образца, мы можем расширить её, чтобы включить новые элементы UI, которые будем использовать в нашей программе. Важно отметить, что необходимо хранить только те элементы, которые вы собираетесь запрограммировать позже, после создания структуры UI.
В этой программе мы добавим два виджета GtkButtons к панели заголовка и воспользуемся вертикальным и горизонтальным элементом GtkBox с некоторыми метками (labels), чтобы отобразить информацию о текущем состоянии нашего приложения. Следующее изображение является нашей новой диаграммой структур.
Что означает следующее в Rust:
# #![allow(unused_variables)] #fn main() { pub struct App { pub window: Window, pub header: Header, pub content: Content, } pub struct Header { pub container: HeaderBar, pub hit: Button, pub heal: Button, } pub struct Content { pub container: Box, pub health: Label, pub message: Label, } #}
Создание структуры App
Следуя последнему уроку, начнём с нашей структуры App. Метод new() должен принимать ссылку на &HealthComponent в качестве вводимого значения в UI. Заметим, что мы добавили новую переменную content типа Context, которая принимает эту ссылку на health.
# #![allow(unused_variables)] #fn main() { impl App { fn new(health: &HealthComponent) -> App { // Создадим новое окно с типом `Toplevel`. let window = Window::new(WindowType::Toplevel); // Создадим заголовок и связанное с ним содержимое. let header = Header::new(); // Расположим содержимое в окне. let content = Content::new(health); // Установим панель заголовка как описание виджета. window.set_titlebar(&header.container); // Установим описание для окна. window.set_title("Боксирующие кнопки"); // Установим класс для оконного менеджера. window.set_wmclass("app-name", "Боксирующие кнопки"); // Установим иконку, отображаемую приложением. Window::set_default_icon_name("имя-иконки"); // Добавим коробку с содержимым в окно. window.add(&content.container); // Запрограммируем выход из программы при нажатии кнопки. window.connect_delete_event(move |_, _| { main_quit(); Inhibit(false) }); // Вернём состояние нашего приложения. App { window, header, content, } } } #}
Создание Header
Затем мы так же реализуем метод для нашего заголовка, который должен содержать два элемента GtkButtons -- кнопка удара и лечения. Также обратите внимание, что мы устанавливаем некоторые классы стилей этим кнопкам, чтобы дать им более информативную визуальную способность.
# #![allow(unused_variables)] #fn main() { impl Header { fn new() -> Header { // Создадим главный заголовочный бар содержащий виджет. let container = HeaderBar::new(); // Установим текст для отображения в секции для названия. container.set_title("Боксирующие кнопки"); // Сделаем активными элементы управления окна в этой панели. container.set_show_close_button(true); // Создадим кнопки: `ударить` и `лечить`. let hit = Button::new_with_label("Ударить"); let heal = Button::new_with_label("Лечить"); // Добавим соответствующие классы стилей к этим кнопкам. hit.get_style_context() .map(|c| c.add_class("destructive-action")); heal.get_style_context() .map(|c| c.add_class("suggested-action")); // Теперь добавим их в панель заголовка. container.pack_start(&hit); container.pack_end(&heal); // Вернём the header and all of it's state Header { container, hit, heal, } } } #}
Создание Content
Теперь пришло время создать содержимое для нашего окна. При создании своего интерфейса (UI) с древовидной диаграммой, вы почти достигните GtkBoxes. При инициализации, эта упаковка должна быть указана с Horizontal или Vertical ориентацией.
Безусловно, вы достигните виджета GtkBoxes для настройки UI. Он может быть создан с Horizontal или Vertical выравниванием. В эти упаковки вы добавите все ваши виджеты, где они будут сложены в соответствии с выравниванием упаковки, к которой они присоединены.
Мы должны создать вертикальную упаковку, которая содержит два дочерних элемента: вертикальный виджет GtkBox содержащий метку и значение, а затем ниже простой виджет GtkLabel.
# #![allow(unused_variables)] #fn main() { impl Content { fn new(health: &HealthComponent) -> Content { // Создадим вертикальную упаковку, чтобы хранить там все дочерние элементы. let container = Box::new(Orientation::Vertical, 0); // Информация о здоровье будет храниться в горизонтальной упаковке вместе с вертикальной. let health_info = Box::new(Orientation::Horizontal, 0); let health_label = Label::new("Текущее значение здоровья:"); let health = Label::new(health.get_health().to_string().as_str()); // Установим горизонтальное выравнивание для наших объектов. health_info.set_halign(Align::Center); health_label.set_halign(Align::Start); health.set_halign(Align::Start); // Добивим информацию о здоровье в дочернюю коробку. health_info.pack_start(&health_label, false, false, 5); health_info.pack_start(&health, true, true, 5); /* * Создадим метку, которая будет изменяться приложением * при выполнении удара или лечения. */ let message = Label::new("Привет"); // Добавим все в нашу вертикальную коробку. container.pack_start(&health_info, true, false, 0); container.pack_start(&Separator::new(Orientation::Horizontal), false, false, 0); container.pack_start(&message, true, false, 0); Content { container, health, message, } } } #}
Устанавливаем выравнивание
Возможно, вы заметили, что приведённый код выше устанавливает горизонтальные выравнивания.
По желанию, с помощью методов set_halign()
и set_valign()
, можно установить выравнивание для виджетов.
# #![allow(unused_variables)] #fn main() { // Установим горизонтальное выравнивание для наших объектов. health_info.set_halign(Align::Center); health_label.set_halign(Align::Start); health.set_halign(Align::Start); #}