Візуальний редактор компонувань The Jucer
Розміщувати компоненти вікна вручну – справа невдячна. На щастя, всю чорну роботу можна покласти на Jucer, який є візуальним редактором інтерфейсу. Запустимо його і виберемо File → New component. Назвемо клас нового компонента MyMainComponent. Інші параметри необов'язково чіпати, але при необхідності можна задати батьківський клас, ініціалізацію полів в конструкторі і попросити Jucer згенерувати додаткові методи для реакції на різноманітні події. Перейдемо на вкладку «Subcomponents» - це і є візуальний редактор, який допомагає розміщувати різні віджети. Контекстне меню дозволяє вставляти стандартні віджети або будь користувальницькі компоненти. Додамо на форму два поля введення і кнопку (див. рис.2.1).
Рис.2.1. Створення нового компонента в The Jucer
При виділенні компонента праворуч відкривається панель його властивостей. Всі вони інтуїтивно зрозумілі, крім властивостей x, y, width і height, які задають геометрію віджета. Поруч з ними є кнопки Mode, які відривають меню режиму розміщення.
Тут потрібно зробити невеличкий відступ. У Juce немає «гумовою» компонування за допомогою сайзеров, як в GTK + або Qt. Замість цього положення віджета можна визначати в абсолютних величинах або щодо будь-якого іншого елемента керування. Логіка такого розміщення на перший погляд досить заплутана, але після декількох хвилин експериментування все стає на свої місця.
Наприклад, спробуємо зробити так, щоб кнопка завжди знаходилася праворуч і мала фіксовану ширину, а поля введення розтягувалися по ширині разом з вікном. Встановлюємо режим властивості x для кнопки Аbsolute distance from right of parent і переміщаємо її до правого краю вікна. Тепер кнопка прив'язана до правої кромці вікна. Її ширина за замовчуванням встановлена в режим Absolute width, тобто вона зберігає ті розміри, які ми її поставили.
Займемося першим полем вводу. За замовчуванням його положення відраховується від лівого краю вікна (Аbsolute distance from left of parent), що нам і потрібно, а ось ширина повинна бути не фіксованою, а залежною від ширини вікна. Встановимо режим поля width в Substracted from width of parent і розтягнемо поле так, щоб залишився лише невеликий зазор до кнопки. Тепер відстані до лівого і правого краю вікна зафіксовані, а ширина змінюється разом з вікном. Оскільки ширина кнопки фіксована, то все працює як треба і віджети не налазять один на одного.
Для другого поля введення можна вчинити так само, а можна встановити режим для width в Relative to textEditor, потім Percentage of width of textEditor і задати значення 100%. Тепер ширина другого поля завжди дорівнює ширині першого.
Виконавши View → Test Component, можна побачити нашу компоновку в дії і переконатися, що все працює як було задумано.
Вибравши File → Save as, зберігаємо компонент. The Jucer генерує файли .h і .cpp для класу MyMainComponent.
Файл MyMainComponent.cpp можна відкрити в The Jucer повторно, при цьому завантажиться створена компоновка. Це досягається включенням у вихідний код спеціальних коментарів, які розпізнаються програмою і містять всі необхідні метадані. Подивившись на згенерований код (це легко зробити на вкладці Code preview) легко переконатися, що написати щось подібне вручну було б вкрай утомливо. Основна «магія» укладена в методі resized (), який викликається при зміні розмірів вікна і потрібним чином вибудовує всі віджети.
У створеному коді у всіх «стратегічних» місцях вставлені блоки такого типу:
//[UserPaint] Add your own custom painting code here.. //[/UserPaint] |
Між такими коментарями (і тільки там!) Можна вставляти будь-який користувацький код. Будь-які зміни в інших місцях будуть втрачені при наступному збереженні файлу в Jucer.
У Juce використовується ідеологія – ієрархія віджетів відповідає ієрархічній вкладеності їх класів в коді, а не встановлюється вручну призначенням «батька», як, наприклад, в Qt. Всі віджети компонента рівноправні і знаходяться на одному рівні ієрархії. Якщо помістити на форму, наприклад, компонент GroupComponent, то віджети, поміщені всередину його рамки, не стануть його нащадками. Їхнє становище доведеться відредагувати вручну, встановлюючи режим Relative to groupComponent. Якщо використовується, наприклад, TabbedComponent, то кожна його вкладка – це незалежний компонент, який потрібно «намалювати» окремо. Властивість Content type кожної вкладки дозволяє вибрати цей компонент по імені або вставити з файлу, попередньо створеного в Jucer. При вставці з файлу компонент відразу відображається на формі, однак редагувати його «на льоту» не можна (це підкреслюється білим фоном без спрямовуючої сітки, див. рис.2.2). На щастя, в Jucer можна відкривати декілька компонувань одночасно. Якщо змінити і зберегти вкладену компоновку, то результат відразу ж буде видно у всіх інших компонуваннях, куди вона входить.
Рис.2.2. Робота з вкладеними компонуваннями в The Jucer
Редактор компонувань в The Jucer страждає від загальної проблеми багатьох тулкіта – відсутність сайзеров і «гумових» компонувань. Чому проста і елегантна ідея сайзеров так непопулярна у творців «альтернативних» тулкіта, абсолютно незрозуміло. І U, і Juce використовують складну і громіздку систему логічного позиціонування, проте наявність прекрасного візуального редактора дещо згладжує недоліки такого підходу в Juce. Можливість вказівки відносної відстані від інших віджетів дозволяє відносно легко створювати компоновки аналогічні звичайним і табличним сайзерам, проте повністю замінити їх вона не може. Попробуйте, наприклад, розташувати по горизонталі три віджету, які повинні міняти ширину в пропорції 1:2:3 при розтягуванні вікна не налезая один на одного!
На щастя, щось подібне сайзерам в Juce таки є. Клас StretchableLayoutManager є по суті дуже незграбним лінійним сайзером. Метод layOutComponents цього класу приймає масив покажчиків на віджети і впорядковує їх згідно з раніше заданим мінімальним, максимальним і віддається перевага розмірам:
//В конструкторе // Первый виджет может иметь размер от 50 до 100 пикселов, // предпочитаемый размер — 60% от размера контейнера myLayout.setItemLayout(0,50,100,-0.6); // Второй виджет может иметь размер от 20% до 60% от размера // контейнера, предпочитаемый размер — 50 пикселов myLayout.setItemLayout(1,-0.2,-0.6,50); // В методе resized() // Создаем массив указателей на виджеты, которые хотим разместить Component* comps[] = { myComp1, myComp2 }; // Размещаем два компонента по вертикали в текущем компоненте myLayout.layOutComponents (comps, 2, 0, 0, getWidth(), ↵ getHeight(),true); |
Якщо в Qt або GTK віджет просто додається в кайзер в конструкторі, а розміри є властивостями самого віджета, то в Juce все складніше. Потрібно точно знати кількість віджетів в сайзере і їх бажані розміри, а в методі resized () доводиться створювати тимчасовий масив покажчиків. Клас StretchableLayoutManager недоступний у візуальному редакторі, що робить його застосування ще більш трудомістким. Тим не менш, навіть такий складний у застосуванні сайзер краще, ніж нічого.
The Jucer дозволяє дуже просто і елегантно працювати з будь-якими бінарними ресурсами. Припустимо, ми хочемо використовувати в програмі графічний файл juce.png. Переходимо на вкладку Resources і додаємо цей файл у список. при збереженні бінарні дані з цього файлу переводяться у форму звичайного масиву С і безпосередньо вставляються в код. Відповідний рядок має вигляд:
static const unsigned char ↵ resource _ MyMainComponent _ juce _ png[] = { 137,80,78,71,... |
У класі автоматично створюється змінна cachedImage_juce_png типу Image *, яка ініціалізується даними цього масиву в конструкторі. Її можна використовувати в коді для доступу до ресурсу. Весь службовий код для роботи з такими ресурсами (а його чимало) створюється автоматично.
Маючи набір графічних файлів, завантажених у вигляді ресурсів, можна переходити до однієї з найбільш вражаючих особливостей The Jucer - редактору фонової графіки (див. рис.2.3). Перейдемо на вкладку Graphics. Тут можна редагувати фон нашого компонента, що відображається під віджетами. З контекстного меню можна додати різні геометричні примітиви, криві, малюнки і текст. Для кожного компонента можна вибрати заливку кольором або у вигляді лінійного або радіального градієнта, товщину і колір ліній і т.п. Контрольні точки градієнтів і кривих можна перетягувати мишею. Також можна задавати прозорість для всіх елементів, заповнювати фігури зображеннями і навіть перетворювати текст в криві. Редактор гранично зрозумілий і дуже приємний в роботі. Його, звичайно, не можна порівнювати з повновагими векторними редакторами зразок Inkscape, але зі своєю функцією створення гарного фону для віджетів він справляється на відмінно.
Рис.2.3. Редагування фонової графіки в The Jucer
Код малювання поміщається в метод paint () нашого класу і, при необхідності, в метод resized (). Вивчивши його, легко зрозуміти логіку роботи операцій малювання в Juce. Зокрема, чітко видно, як The Jucer бере на себе всю чорну роботу по масштабуванню і розміщенню примітивів при зміні розмірів вікна.
