Працюємо з mono частина 4

Коротко про Glade і Glade #

Glade - це конструктор для користувача інтерфейсу для роботи з кроссплатформенной бібліотекою елементів інтерфейсів Gtk в робочому середовищі GNOME, який дозволяє відокремити зовнішнє представлення програми від її логіки роботи. По суті, Glade - це вільно поширюване додаток для візуального створення графічних інтерфейсів на основі кроссплатформенной бібліотеки GTK +. А ось Glade # - це набір зв'язків з libglade на мові C #, тобто бібліотека в складі пакету C # для створення призначеного для користувача інтерфейсу.

До створення Glade розробка користувальницького інтерфейсу була вкрай незручним і тривалим заняттям. Весь інтерфейс описувався безпосередньо на мові C ++ і до компіляції і запуску програми програміст не міг подивитися, як цей інтерфейс виглядає на екрані. Glade дозволив перенести розробку інтерфейсу на більш якісний, візуальний рівень.

Згодом з'явилися інструменти, які за допомогою засобів візуального програмування будують інтерфейс, не використовуючи Glade (наприклад, Stetic, що входить до складу середовища MonoDevelop). Однак у Glade є одна істотна перевага. Опис інтерфейсу, розробленого в Glade, відокремлене від вихідного коду програми і являє собою окремий документ формату XML. Це дає можливість, наприклад, створити кілька варіацій інтерфейсу, щоб користувач міг задіяти найбільш зручний йому.

Опис інтерфейсу, створене Glade в форматі XML, і вихідний код програми зв'язуються між собою за допомогою функцій бібліотеки libglade або функцій GtkBuilder, що входять до складу об'єктного бібліотеки GTK +. Тобто Glade дозволяє описувати інтерфейс в двох різних форматах - libglade (всі версії Glade) і GtkBuilder (починаючи з версії Glade 3). Зрозуміло, що для роботи з описом інтерфейсу в форматі libglade необхідна наявність однойменної бібліотеки в системі. В останніх версіях бібліотеки GTK + були введені спеціальні об'єкти, які дозволяють завантажувати файли формату GtkBuilder без установки інших, додаткових бібліотек. Це «спрощення» перевело формат libglade в розряд застарілих, тому тепер творцям інтерфейсів рекомендується віддавати перевагу форматам GtkBuilder.

У середовищі Mono для роботи з Glade-файлами можна використовувати засоби GTK # (для роботи з GtkBuilder) або спеціальну «обгортку» Glade # для бібліотеки libglade (набір зв'язків для роботи з форматами бібліотеки libglade на мові C #).

В ОС Ubuntu установку можна здійснити з центру додатків Ubuntu в розділі "Інструменти розробника -> Розробка графічних інтерфейсів".

Працюємо з mono частина 4

У разі, якщо центр додатків недоступний (наприклад, не встановлений або використовується старіша версія Ubuntu), то можна встановити останню, доступну в репозиторії, версію Glade за допомогою команди apt-get:

Ті, хто бажає отримати найсвіжішу версію Glade, можуть завантажити її з сайту проекту.

Якщо Ви все-таки плануєте використовувати файли формату libglade, упевніться, що встановлені збірки glade-sharp:

Розробка інтерфейсу за допомогою Glade

Перед створенням будь-якого інтерфейсу необхідно продумати його специфікацію, а потім побудувати дерево віджетів.

Для простоти (а також, щоб порівняти різні підходи до створення інтерфейсу) скористаємося вікном з попередньої статті, присвяченій GTK #.

Інтерфейс програми для знаходження коренів рівнянь

Працюємо з mono частина 4

Запозичимо з цього прикладу ієрархію віджетів на вікні.

Ієрархія віджетів для нашого інтерфейсу

Працюємо з mono частина 4

Після того, як буде опрацьована концепція інтерфейсу, починаємо будувати його, використовуючи Glade. Відразу після запуску Glade на екрані з'являється вікно властивостей, де можна вибрати необхідні параметри проекту. Розглянемо їх докладніше.

параметри проекту

Вікно властивостей проекту

Працюємо з mono частина 4

Розділ "Формат файлу проекту" дозволяє вибрати, який тип файлу з описом інтерфейсу буде згенеровано (GtkBuilder або libglade).

Розділ "Імена об'єктів унікальні" дозволяє вказати стиль перевірки унікальності імен об'єктів. Якщо перемикач встановлений в положення "в рамках проекту", то імена об'єктів у всьому проекті не можуть збігатися. Якщо перемикач встановлений в положення "для кожного вікна", то буде перевірятися тільки унікальність імен об'єктів в межах вікна, в різних вікнах одного проекту імена можуть повторюватися.

Розділ "Зображення завантажуються" вказує додатком Glade, звідки брати файли з зображеннями, якщо вони необхідні віджетів. Це може бути каталог проекту, каталог, заданий щодо каталогу проекту, або каталог, розташований за абсолютним шляху.

Розділ "Необхідна версія бібліотек" дозволяє вибрати, для якої версії Gtk + створюватиметься інтерфейс, тобто виконуватися власне створюване додаток. Оптимально вибирати саму останню версію, однак, якщо ви хочете, щоб додаток працювало на старіших версіях, потрібно вказати найменшу, підтримувану на Ваших платформах версію.

При натисканні на кнопку "Виконати" в розділі "Перевірити версії і знайти застарілі віджети" відбувається перевірка побудованого інтерфейсу. За її результатами виводиться повідомлення. Якщо помилок не знайдено, це означає, що все віджети, використовувані в проекті актуальні для заданої версії GTK +:

Працюємо з mono частина 4

У разі, якщо в проекті містяться підтримуються заданої версією віджети (наприклад, відкривається опис інтерфейсу, створене для версії GTK + 2.16, а в параметрах проекту вказана версія GTK + 2.12), то з'явиться повідомлення, що перевірка не пройшла, і список знайдених помилок:

Працюємо з mono частина 4

створюємо інтерфейс

Наступний крок - створення шаблону нового вікна і присвоєння йому імені "MainWindow". Для цього задаємо такі параметри, як заголовок вікна ( "Розрахунок коренів рівняння"), позиція вікна (позиція при запуску, виберемо "по центру"), ширину і висоту вікна при запуску.

Працюємо з mono частина 4

Далі, використовуючи вкладку "Основні", встановлюємо розмір кордону вікна в 6 пікселів.

Працюємо з mono частина 4

Для обробки сигналів управління вікном на вкладці "Сигнали" додамо обробник сигналу destroy (актівірутся при знищенні вікна) батьківського об'єкта GtkObject і призначимо йому обробник on_MainWindow_destroy (вихід з програми).

Працюємо з mono частина 4

Про вкладці "Сигнали" і про сигнали в принципі потрібно розповісти трохи докладніше.

Дані, які використовуються на цій вкладці, організовані у вигляді декількох колонок.

У колонці "Сигнали" перераховуються сигнали обраного віджета, згруповані за ієрархією батьківських об'єктів. Колонка "Оброблювач" спочатку заповнюється ім'ям функції, яка повинна бути викликана при активізації сигналу. Слід зауважити, що як тільки ми додамо обробник, з'явиться ще один рядок для даного сигналу:

Наявність цього рядка дозволяє додати ще один обробник для сигналу. Таким чином, можна додати кілька обробників для одного сигналу, які будуть викликані послідовно.

Колонка "Дані користувача" може містити ім'я об'єкта, визначеного в Glade-файлі, який буде передаватися в обробник.

Колонка "Після" містить прапорець. Якщо цей прапорець встановлений, то заданий обробник буде викликатися після обробника за умовчанням.

У більшості випадків колонки "Дані користувача" і "Після" не використовуються.

Повернемося до розробки інтерфейсу. Керуючись деревом віджетів, отриманим при проектуванні інтерфейсу, додаємо VBox з трьома рядками. У перший рядок додаємо Frame, всередині розміщуємо HBox з двома колонками і в кожної з колонок розміщуємо RadioButton. Також не забудемо прописати у властивостях тексти для міток. До цього моменту інтерфейс виглядає наступним чином:

Працюємо з mono частина 4

Як бачимо, обидва перемикача встановлені як активні. Це не вірно, оскільки вони повинні бути залежні один від одного. Для того, щоб виправити ситуацію, потрібно, вибравши radiobutton2, клацнути на кнопці ". "Збоку від властивості" Група ". У вікні, поставимо крапку (встановимо прапор) зліва від radiobutton1, яка буде говорити, що radiobutton2 відноситься до тієї ж групи, що і radiobutton1.

Працюємо з mono частина 4

Слід звернути увагу, що для radiobutton1 таку операцію проробляти не треба, більше того - це помилка. Алгоритм роботи такий, що спочатку створюється radiobutton1 і до неї приєднується radiobutton2. Тепер перемикачі стали залежними:

Працюємо з mono частина 4

Діючи далі по дереву віджетів, додаємо решту віджети вікна. В кінцевому результаті має вийти наступний варіант інтерфейсу:

Працюємо з mono частина 4

Додамо в наш інтерфейс останні штрихи. При старті поле введення для коефіцієнта C має бути неактивно, так як спочатку у нас активний перемикач для лінійного рівняння, яке не має коефіцієнта C. Щоб дотримати це усоловіе потрібно для поля entry3 змінити властивість Загальні -> Чутливий з "Так" на "Ні" .

На завершення додаємо обробники сигналів:

  1. Для radiobutton1 встановимо обробник сигналу toggled в групі GtkToggleButton. Ім'я обробника on_radiobutton1_toggled.
  2. Для radiobutton2 встановимо обробник сигналу toggled в групі GtkToggleButton. Ім'я обробника on_radiobutton2_toggled.
  3. Для кнопки button1 (Розрахувати) встановимо обробник сигналу clicked в групі GtkButton. Ім'я обробника on_button1_clicked.
  4. Для кнопки button2 (Вихід) встановимо обробник сигналу clicked в групі GtkButton. Ім'я обробника on_button2_clicked.

Щоб розглянути два варіанти використання інтерфейсу (за допомогою Glade # і за допомогою GtkBuilder) збережемо файл в двох форматах: Glade - з ім'ям GladeUI.glade і GtkBuilder - як GtkBuilderUI.glade.

Завантаження Glade-файлів в додаток (формат libglade)

Створимо файл GladeTest.cs такого змісту:

Звернемо увагу на ключові моменти в наступних рядках:

У цьому рядку завантажується інтерфейс з файлу формату Glade XML. Першим параметром вказується ім'я файлу з описом інтерфейсу, а другим - ім'я головного вікна, що завантажується з файлу. Справа в тому, що в файлі Glade XML може розміщуватися кілька вікон верхнього рівня. Слід звернути увагу, що ім'я віджета обов'язково має бути одним і тим же і в описі інтерфейсу, і в другому параметрі. Третій параметр відповідає за інтернаціоналізацію і поки нам не цікавий.

Ця команда виконує автоматичне приєднання оброблювачів до сигналів. Для правильної роботи в коді програми необхідно використовувати методи обробки сигналів, імена яких збігаються з іменами оброблювачів в XML-описі інтерфейсу.

За допомогою методу GetWidget можна отримати об'єкт віджета по його назві. Це необхідно для виклику методів обробки для цього віджета. Зокрема, для показу вікна можна викликати в ньому метод Show.

Існує й інший спосіб отримання віджетів по їх імені, за допомогою атрибута Glade.Widget:

Як параметр атрибуту передається ім'я віджета.

Тепер, користуючись отриманими з даної і попередньої статті відомостями, реалізуємо функціональність знаходження коренів рівнянь. Повний код програми наведено в файлі GladeTest.cs.

Результат запуску додатка

Працюємо з mono частина 4

Єдиним недоліком отриманого програми є те, що воно працює тільки з соответсвтвующім файлом XML, тобто разом з GladeTest.exe файлом повинен поширюватися файл GladeUI.glade з описом інтерфейсу. Якщо XML-файл загубиться, то програма працювати не буде.

Щоб запобігти цьому, можна впровадити XML-файл в ресурси збірки. Для цього потрібно дати вказівку компілятору про розміщення XML всередині збірки як один з ресурсів:

Але перш, перед компіляцією, потрібно поміняти один рядок у вихідному коді:

Саме вона вказує додатком, що документ слід завантажувати з ресурсів збірки.

Завантаження Glade-файлів в додаток (формат GtkBuilder)

На жаль нормальної підтримки GtkBuilder в стабільній версії GTK # (на поточний момент це 2.12.10) немає. Розробники вирішили не випускати версію 2.14, а сконцентруватися на більше широкому релізі GTK # 3.0. Проте існують збірки версії 2.14.x, які можна використовувати для роботи (треба тільки пам'ятати, що вони нестабільні).

Щоб отримати можливість працювати з форматом GtkBuilder, необхідно встановити бібліотеки gtk-sharp-beans, розроблені Stephane Delcroix. У Maverik Meerkat (Ubuntu 10.10) потрібні бібліотеки, швидше за все, будуть входити в один зі штатних репозиторіїв. Для більш старих версій потрібно скористатися сторонніми репозиторіями:

І далі встановити два пакети:

Довгі пошуки будь-якої зрозумілої документації по gtk-sharp-beans ні до чого не привели, тому довелося звернутися до вихідного коду. Бажають докладніше розібратися з бібліотекою можуть взяти код тут.

Подивимося, які зміни будуть необхідні, якщо використовувати для ініціалізації інтерфейсу файл формату GtkBuilder. В якості основи візьмемо вже існуючий вихідний код GladeTest.cs і збережемо його під ім'ям GtkBuilderTest.cs.

У найпростішому випадку потрібно замінити всі об'єкти Glade.XML на GtkBeans.Builder і всі атрибути [Glade.Widget] на [GtkBeans.Builder.Object].

Нижче наведено ділянку вихідного коду, який був перероблений:

Зауважимо, що при компіляції не має сенсу вказувати параметр -pkg: glade-sharp-2.0, так як Gtk.Builder включений до складу gtk-sharp і необхідно додати лише складання -pkg: gtk-sharp-beans2.0. XML файл включимо в ресурси:

За замовчуванням бібліотеки gtk-sharp-beans не можуть встановлюватися в GAC, тому перед запуском потрібно додати каталог з ними в змінну оточення MONO_PATH:

Тепер можна запускати додаток:

GtkBuilder проти Glade #

Ну і наостанок розглянемо один досить цікавий метод, реалізований в GtkBuilder, який показує незаперечну перевагу GtkBuilder перед Glade #. Це метод GetRawObject, що дозволяє створювати віджети, завантажені з XML-файла, але при цьому дозволяють з ними працювати безпосередньо як з об'єктами GTK #.

Змінимо наш приклад і збережемо його під ім'ям GtkBuilderTest_RawData.cs.

Всі методи, крім Main, внесемо у вкладений клас MainWindow, успадкований від Gtk.Window і отримаємо в ньому об'єкт з Builder:

Обробники подій також будуть внесені всередину класу MainWindow. Єдине, що в них потрібно виправити - це змінити параметр main_wnd в конструкціях new MessageDialog на параметр this.

Функція Main зазнає такі зміни:

висновок

В даний момент для побудови інтерфейсу за допомогою засобів GTK # найбільш застосовна технологія Glade #. Хоча вона і визнана застарілою, але той факт, що стабільної реалізації GtkBuilder поки не існує, змушує використовувати саме її.

Однак будемо сподіватися, що реліз GTK # 3 не за горами і скоро для того, щоб скористатися міццю GtkBuilder, не доведеться встановлювати сторонні нестабільні бібліотеки.

Самі ж технології Glade # і GtkBuilder дозволяють створювати різні інтерфейси для одного і того ж додатка згідно з різними побажаннями різних користувачів.

Схожі статті