Источник: https://docs.wxwidgets.org/3.1/overview_xrc.html
XRC был написан Вацлавом Славиком. XRC позволяет в текстовых файлах хранить элементы интерфейса (диалоги, панели меню, панели инструментов и т.д.) и загружать их во время выполнения.
Файлы XRC также могут быть скомпилированы в двоичные файлы XRS или в код C ++, первый вариант позволяет хранить все ресурсы в одном файле, а второй полезен, когда нужно внедрить ресурсы в исполняемый файл.
Начало работы с XRC
Все элементы XRC можно хранить как в одном файле, так и в нескольких.
Сгенерированный класс окна может быть использован как основа для полного класса окна. К членам класса, представляющим виджеты, в любой момент можно получит доступ по имени путем ссылки на них, вместо использования макроса
К wxSizerItem также можно получить доступ как к части ресурса с помощью макроса
Реализация нашего пользовательского обработчика XML обычно выглядит так:
В документации wxXmlResourceHandler можно узнать, сколько встроенных геттеров скобы узнать, есть сколько встроенных геттеров. С их помощью очень легко извлекать сложные структуры из XRC-файлов.
XRC был написан Вацлавом Славиком. XRC позволяет в текстовых файлах хранить элементы интерфейса (диалоги, панели меню, панели инструментов и т.д.) и загружать их во время выполнения.
Файлы XRC также могут быть скомпилированы в двоичные файлы XRS или в код C ++, первый вариант позволяет хранить все ресурсы в одном файле, а второй полезен, когда нужно внедрить ресурсы в исполняемый файл.
Преимуществ использования ресурсов XRC:
- Не требуется повторная компиляция и линковка при изменении файла ресурсов.
- Бывает, что используемый конструктор диалогов генерирует код на C ++, который сложно интегрировать с существующим кодом на C ++. Разделение ресурсов и кода - более элегантное решение.
- При необходимости, во время выполнения можно делать выбор между различными файлами альтернативных ресурсов.
- Формат XRC использует сайзеры, что обеспечивает гибкость, можно создавать диалоги изменяемого размера и повторно использовать их в разных местах.
- Формат XRC является стандартом wxWidgets и может генерироваться или обрабатываться любой программой, которая его понимает. Так как он основан на стандарте XML, для простого редактирования можно использовать существующие редакторы XML.
Создание файла XRC
Создадим файл XRC. Хотя это можно сделать вручную даже в блокноте, все же рекомендуется использовать специализированный инструмент. К ним относятся:
Не бесплатно :
- DialogBlocks http://www.anthemion.co.uk/dialogblocks/ , редактор коммерческого диалога.
Свободно:
- XRCed http://xrced.sourceforge.net/ , редактор диалогов на основе wxPython.
- wxFormBuilder http://wxformbuilder.org/ , конструктор форм на C++, который формирует код C++, XRC или python.
- wxCrafter (бесплатная версия) http://www.codelite.org/wxcrafter/ , конструктор форм на C++, который формирует код C++ или XRC.
См. также: https://wiki.wxwidgets.org/Tools.
...
И так, файл XRC. Содержит простой диалог:
<?xml version="1.0" ?>
<resource version="2.3.0.1">
<object class="wxDialog" name="SimpleDialog">
<title>Simple dialog</title>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxTextCtrl" name="text"/>
<option>1</option>
<border>10</border>
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<object class="sizeritem">
<object class="wxButton" name="clickme_btn">
<label>Click</label>
</object>
<flag>wxRIGHT</flag>
<border>10</border>
</object>
<object class="sizeritem">
<object class="wxButton" name="wxID_OK">
<label>OK</label>
</object>
<flag>wxLEFT</flag>
<border>10</border>
</object>
<orient>wxHORIZONTAL</orient>
</object>
<flag>wxALL|wxALIGN_CENTRE</flag>
<border>10</border>
</object>
</object>
</object>
</resource>
Загрузка XRC файлов
Для использования файлов XRC в приложении, их предварительно следует загрузить. Фрагмент кода ниже показывает, как загрузить единственный файл XRC с именем "resource.xrc" из текущей рабочей директории, а также все файлы the *.xrc, содержащиеся в поддиректории "rc".
Загрузка ресурсных XRC - в начале работы приложения - обычное дело. Позднее можно выгрузить эти файлы, но такое необходимо редко.
Использование элемента XRC
И так, мы загрузили XRC файл(ы) в виртуальную файловую систему приложения. Начиная с этого момента, нужно выполнить другой тип загрузки, в случае, когда нужно использовать отдельный объект. Возможно сказанная фраза звучит коряво, но сначала нужно загрузить Load() файл, а только затем загрузить каждый нужный объект верхнего уровня..
Описанный выше простой диалог можно использовать в своем коде следующим образом:
То есть, все просто. Вся реализация делается системой XRC.
Хотя, чаще всего придется использовать wxXmlResource::LoadDialog, также есть эквиваленты, которые загружают фрейм, меню, и т.п.; и общий метод wxXmlResource::LoadObject. См. подробности в wxXmlResource.
Доступ к дочерним контролам XRC
Выше было показано, как загружать окна верхнего уровня типа диалогов, но как насчет вложенных в диалог окон вроде wxTextCtrl с именем "text", которые которые содержат текст? Возможности таким же способом загрузить отдельный контрол нет. Вместо этого используем макро XRCCTRL, возвращающее указатель на дочерний элемент. Расширим предыдущий код:
void MyClass::ShowDialog()
{
wxDialog dlg;
return;
if (pText)
pText->ChangeValue("This is a simple dialog");
dlg.ShowModal();
}
XRCCTRL получает ссылку на родительский контейнер и использует wxWindow::FindWindow для поиска внутри wxWindow элемента с указанным именем (это имя - "text"). И возвращает указатель на контрол, приведенный к типу третьего параметра; то же самое можно сделать и следующим образом:
XRC и идентификаторы (ID-ы)
Часто бывает нужен ID контрола, например для использования в таблице событий или в методе wxEvtHandler::Bind. Его несложно найти, передав имя котрола в макрос XRCID:
void MyClass::ShowDialog()
{
wxDialog dlg;
return;
wxTextEventHandler(MyClass::OnTextEntered), this, XRCID("text"));
XRCCTRL(dlg, "clickme_btn", wxButton)->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(MyClass::OnClickme), this, XRCID("clickme_btn"));
dlg.ShowModal();
}
Замечания:
- Значение типа int, возвращаемое XRCID("foo") является гарантированно уникальнымв рамках приложения.
- Тем не менее, не следует надеяться, что оно будет равно какой-то заранее известной это величине, и не следует опираться полагаться на это значение как на основу при реализации взаимодействия между программами. В разных приложениях оно может быть разным.
- Зарезервированные значения идентификаторов, такие как wxID_OK работаю верно и не требуют XRCID (так как внутри XRCID("wxID_OK") отображается на wxID_OK).
- И XRCID и XRCCTRL используют 'name' контрола (такое, как в wxWindow::GetName). Оно отличается от мети, которую пользователь видит, например, на поверхности wxButton.
Наследование классов в XRC
Возможно, понадобится создавать наследников классов контролов wx. Для наследования классов контролов из XRC есть три способа:
- Весьма редкоиспользуемый способ, в котором придется создать свой собственный wxXmlResourceHandler
- Иногда лучше использовать wxXmlResource::AttachUnknownControl. См. Неизвестные Объекты
- Обычно достаточно применения ключевого слова 'subclass'.
Предположим, мы хотим, чтобы контрол wxTextCtrl под именем "text" создавался как наш производный класс MyTextCtrl. Нужно изменить одну строчку XRC файла:
<object class="wxTextCtrl" name="text" subclass="MyTextCtrl"/>
Далее, в XRCCTRL следует указать MyTextCtrl. Однако, чтобы подклассы создавались правильно, важно быть уверенным, что он использует wxWidget-овский механизм RTTI: см. Subclassing.
Пример XRC
Основным ресурсом для изучения XRC является XRC Sample. Он демонстрирует все стандартные методы использования XRC, и некоторые из менее распространенных. Весьма рекомендуется к изучению для понимания работы XRC (код хорошо документирован).
Двоичные ресурсные файлы
Чтобы скомпилировать двоичный ресурсный файл, следует использовать утилиту командной строки
wxrc
. Она принимает один или больше параметров(входных файлов XRC) и следующих ключей и параметров:- -h (--help): Показывает справочное сообщение.
- -v (--verbose): Показывает подробную информацию при работе.
- -c (--cpp-code): Создает C++ - исходник, а не файл XRS.
- -e (--extra-cpp-code): Если используется с -c, генерируется заголовочный файл C++, содержащий определения окон, определенных в файле XRC (см. специальные подразделы).
- -u (--uncompressed): Не сжимает файлы XML (только для C++).
- -g (--gettext): Выводит выровненные с помощью символа подчеркивания строки, которые могут быть сканированы poEdit или gettext. Вывод в stdout, или в файл, если используется -o.
- -n (--function) <name>: Задает имя функции C++ (используется с -c).
- -o (--output) <filename>: Задает выходной файл, например resource.xrs или resource.cpp.
- -l (--list-of-handlers) <filename>: Выводит в этот файл список необходимых обработчиков.
Например:
$ wxrc resource.xrc
$ wxrc resource.xrc -o resource.xrs
$ wxrc resource.xrc -v -c -o resource.cpp
- Замечание
- Файл XRS фактически является переименованным ZIP архивом, что означает, что мы можем манипулировать с ним стандартными инструментами ZIP. Отметим, что при использовании файлов XRS сперва нужно инициализировать обработчик архива wxFileSystem, это очень просто::
#include <wx/filesys.h>
#include <wx/fs_arc.h>
...
wxFileSystem::AddHandler(new wxArchiveFSHandler);
Использование внедренных ресурсов
Порой полезно внедрять ресурсы прямо в исполнительный файл вместо загрузки внешнего файла (например, наше приложение крошечное и содержит только один exe файл). XRC предоставляет средства для преобразования ресурсов в обычный C++ файл, который может быть откомпилирован и включен в исполняемый файл.
Для создания C++ файла со встроенными ресурсами. Этот файл будет содержать функцию с именем
InitXmlResource
(если вы не переопределите это с помощью ключей в командной строке). Использование ее для загрузки ресурса:
extern void InitXmlResource(); // defined in generated file
...
wxXmlResource::Get()->InitAllHandlers();
InitXmlResource();
...
Генерация заголовочного файла C++
Использование ключа
-e
совместно с ключом -c создает заголовочный файл
C++, содержащий определения класса для окон, определенных в файле XRC. Генерация этого кода может облегчить использование XRC и автоматизировать разработку программ. Классы могут быть использованы в качестве основы для разработки, освобождая программиста от многих особенностей, связанных с XRC (например, от применения XRCCTRL
).
Для каждого окна верхнего уровня, определенного в файле XRC, генерируется определение класса C++, содержащего в качестве членов класса виджеты окна. Для каждого класса также генерируется конструктор по умолчанию. Внутри конструктор выполняется вся загрузка XRC и выполняется инициализация всех членов класса, представляющих виджеты.
Следующий простой пример позволит помочь понять, как работает эта схема. Предположим, у нас есть файл XRC, в котором определено окно верхнего уровня
TestWnd_Base
, которое является сабклассом wxFrame (любой другой класс, вроде wxDialog будет работать точно также
), и имеющий виджеты wxTextCtrl A и wxButton B.
Файл XRC и соответствующее определение класса в заголовочном файле будет примерно такими:
<?xml version="1.0"?>
<resource version="2.3.0.1">
<object class="wxFrame" name="TestWnd_Base">
<size>-1,-1</size>
<title>Test</title>
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<object class="wxTextCtrl" name="A">
<label>Test label</label>
</object>
</object>
<object class="sizeritem">
<object class="wxButton" name="B">
<label>Test button</label>
</object>
</object>
</object>
</object>
</resource>
{
protected:
wxTextCtrl* A;
wxButton* B;
private:
void InitWidgetsFromXRC()
{
}
public:
TestWnd::TestWnd()
{
InitWidgetsFromXRC();
}
};
XRCCTRL
(отметим, что они - защизенные члены класса), хотя мы все еще может использовать XRCID
для ссылки на IDs виджетов в таблице событий.
Пример:
#include "resource.h"
class TestWnd : public TestWnd_Base
{
public:
TestWnd()
{
// A, B already initialised at this point
A->SetValue("Updated in TestWnd::TestWnd");
B->SetValue("Nice :)");
}
void OnBPressed(wxEvent& event)
{
Close();
}
};
wxBEGIN_EVENT_TABLE(TestWnd,TestWnd_Base)
EVT_BUTTON(XRCID("B"), TestWnd::OnBPressed)
XRCSIZERITEM, как показано ниже.
Ресурсный файл
может иметь сайзер вроде такого:
<object class="spacer" name="area">
<size>400, 300</size>
</object>
Код для доступа к элементу - сайзеру с помощью
XRCSIZERITEM (а также
и XRCID)
:Добавление новых обработчиков ресурсов
Добавить новые обработчики ресурсов довольно просто.
Как правило, для добавления обработчика класса
MyControl
, нам нужно создать файлы xh_mycontrol.h
и xh_mycontrol.cpp
.
Заголовочный файл должен содержать определение класса
MyControlXmlHandler
:
{
public:
// Constructor.
MyControlXmlHandler();
// Creates the control and returns a pointer to it.
// Returns true if we know how to create a control for the given node.
// Register with wxWidgets' dynamic class subsystem.
wxDECLARE_DYNAMIC_CLASS(MyControlXmlHandler);
};
Реализация нашего пользовательского обработчика XML обычно выглядит так:
// Register with wxWidgets' dynamic class subsystem.
wxIMPLEMENT_DYNAMIC_CLASS(MyControlXmlHandler, wxXmlResourceHandler);
MyControlXmlHandler::MyControlXmlHandler()
{
// this call adds support for all wxWidgets class styles
// (e.g. wxBORDER_SIMPLE, wxBORDER_SUNKEN, wxWS_EX_* etc etc)
AddWindowStyles();
// if MyControl class supports e.g. MYCONTROL_DEFAULT_STYLE
// you should use:
// XRC_ADD_STYLE(MYCONTROL_DEFAULT_STYLE);
}
wxObject *MyControlXmlHandler::DoCreateResource()
{
// the following macro will init a pointer named "control"
// with a new instance of the MyControl class, but will NOT
// Create() it!
XRC_MAKE_INSTANCE(control, MyControl)
// this is the point where you'll typically need to do the most
// important changes: here the control is created and initialized.
// You'll want to use the wxXmlResourceHandler's getters to
// do most of your work.
// If e.g. the MyControl::Create function looks like:
//
// bool MyControl::Create(wxWindow *parent, int id,
// const wxBitmap &first, const wxPoint &posFirst,
// const wxBitmap &second, const wxPoint &posSecond,
// const wxString &theTitle, const wxFont &titleFont,
// const wxPoint &pos, const wxSize &size,
// long style = MYCONTROL_DEFAULT_STYLE,
// const wxString &name = wxT("MyControl"));
//
// Then the XRC for your component should look like:
//
// <object class="MyControl" name="some_name">
// <first-bitmap>first.xpm</first-bitmap>
// <second-bitmap>text.xpm</second-bitmap>
// <first-pos>3,3</first-pos>
// <second-pos>4,4</second-pos>
// <the-title>a title</the-title>
// <title-font>
// <!-- Standard XRC tags for a font: <size>, <style>, <weight>, etc -->
// </title-font>
// <!-- XRC also accepts other usual tags for wxWindow-derived classes:
// like e.g. <name>, <style>, <size>, <position>, etc -->
// </object>
//
// And the code to read your custom tags from the XRC file is just:
control->Create(m_parentAsWindow, GetID(),
GetBitmap(wxT("first-bitmap")),
GetPosition(wxT("first-pos")),
GetBitmap(wxT("second-bitmap")),
GetPosition(wxT("second-pos")),
GetText(wxT("the-title")),
GetFont(wxT("title-font")),
GetPosition(), GetSize(), GetStyle(), GetName());
SetupWindow(control);
return control;
}
bool MyControlXmlHandler::CanHandle(wxXmlNode *node)
{
// this function tells XRC system that this handler can parse
// the <object class="MyControl"> tags
}
Комментариев нет:
Отправить комментарий