Несколько мыслей о QtE5

Основное - это новый режим распределение памяти который позволяет более эффективно и правильно работать с памятью. Если крадко, то организован подсчет созданных и разрушенных объектов. На основании этой информации производится перестановка вызовов деструкторв C++.

Главное правило, которое нужно соблюдать при работе с QtE5 - теперь нет конструкторов без параметров. То есть, обязательно необходимо при создании нового объекта передать какие-нибудь параметры. Это вызвано тем что конструктор без параметров специально отключён для правильного определения цепочки вызова родителей. По этому еще раз говорю, что главное это конструктор с параметрами.

Для проверки правильности написания конструктора лучше всего посмотреть, как они определены в QtE5.d Обычно Я открываю параллельно в редакторе исходный текст qte5.d и там при помощи обычного поиска смотрю как равильно вызвать конструктор. Например нам нужно создать объект типа QWidget. Вопрос какие у него параметры для конструктора? В окне редактора говорю поиск: class Qwidget и соответственно сразу попадаю на описание данного класса.

Сейчас существуют два вида классов в системе, которые довольно сильно отличаются друг от друга. Первые, это те которые имеют родителя, как правило Qwidget. То есть это визуальные объекты которые непосредственно отображаются на экране. Для них обязательно наличие параметра в конструкторе - это родитель parent.

Второй Класс – это классы которые могут не иметь параметров для конструктора. Это так называемые простые классы К ним относятся классы которые не имеют выхода на Qwidget. Это например: Qpoint, Qrectangle и так далее. У таких классов допустим вызов конструктора без параметров. Однако лучше всего посмотреть непосредственно в файле, каков вид вызова конструктора нужного класса.

Третий вид классов - это так называемые выравниватели QLayout. Они имеют в своём составе конструктор с параметром. Однако вопрос, что передать в качестве параметра, this или null. Для этих классов нужно в качестве параметра ставить null. Дело в том что при вставке одного объекта в другой автоматически происходит переустановка parent. Таким образом, если мы точно вставляем один объект в вругой (QLayout яркий пример) то вставляемый виджет будет определяйться с parent объекта в который вставляется. Переопределение происходит автоматически.

Все имеющиеся сейчас классы описаны в библиотеке так как они описаны в документации по Qt-5 (на на 98%. с сохранением имен функций, параметров и т.д.). Таким образом для просмотра возможностей данного класса проще всего посмотреть документацию в интернете на данный класс Qt-5. Бывает иногда, что есть несовпадение с передачей параметров, связанные с тем, что возможно могут быть переставлены параметры местами или добавлен какой-нибудь дополнительный параметр. Таких случаев довольно мало. Описать полностью все методы тяжело, по этому я стараюсь описать только самые важные, самые применяемые. Всегда можно дописать свой собственный метод, глядя на то как это сделано в Qte5Widget.cpp.

Написать документацию для библиотеки очень сложно. Это связано с тем что постоянно что-то меняется. Примеры тоже сложное мероприятие. Их надо придумать, их надо реализовать, проверить и они устаревают. По этому я в начале писал примеры а потом перестал это делать. Сейчас основным примером для проверки работоспособности системы является приложение под названием ide5. Именно в нём самые современные методы программирования применяемые для построения графического интерфейса. Это и работа с Painter, и работа с выравнивателями (QLayout), работа с панелями, работа с мышью и так далее. Таким образом рассматривая исходный текст ide5 можно посмотреть на наиболее интересные и сложные в объяснении моменты применения библиотеки QtE5.

Сейчас я начал работу над новой концепцией в самой библиотеке. Это связано мыслью попробовать заменить некоторые классы структурами. Применение структуры позволяет смоделировать ситуацию C++, когда объект создается непосредственно на стеке а не в хипе. D по умолчанию все объекты создаются в хипе, в C++ можно выбирать где конкретно создать объект в хипе или на стеке. D все объекты создаются строго в хипе. Кстати это точно также как и Delphi (FreePascal Lazarus). Там все объекты создаются строго в хипе. Так как работа на стеке с объектами быстрее, чем в хипе, то потенциально C++ самый быстрый. Если посмотреть примеры C++ Qt, то можно увидеть что в рамках одной функции создается очень много объектов которые потом уничтожаются выходя из этой функции. Это как раз и есть работа с объектами на стеке. По умолчанию в D такой возможности нету. По этому не следует создавать много объектов и уничтожать их непосредственно в рамках одной функции. Особенно если эта функция часто вызывается. Это в первую очередь относится к обработчиком различных событий.

Cейчас я пробую новый вариант работы на стеке (как C++). Для этих целей использую структуры D. Структура хороша тем что создаётся и уничтожается полностью на стеке. Однако не все так просто. Отсутствие режима наследование методов, создает трудности и по этому тяжело применить для описания полной цепочки методов в классах связанных иерархических. Сейчас структуры для описания объектов у меня применяются выборочно и в небольших количествах. По правильному желательно написать полную копию всех объектов которые сейчас реализованы. Что бы была возможность выбирать что использовать либо класс либо структуру. Замеры показали что структура приблизительно на 10% быстрее чем класс.

Теперь что касается деструкторов. Сами деструкторы явно вызывать Не надо. Так как при удалении автоматически происходит удаление объектов в С++ Qt. Правильность удаления объектов Qt обеспечивается вложенностью виджетов друг в друга. Однако если вам явно нужно удалить какой-то объект созданный в рамках одной функции то нужно создать и удалить объект используя New и delete. Данный момент нужно применять с осторожностью. Просто так удалить объект возможно только если вы создали его не привязав и не вставив не в один виджет. Обычно такие объекты, это маленькие объекты про которые я уже говорил. Линия прямоугольник и так далее.

Правильная работа со сложными иерархическими объектами, особенно если они часто переписываются, это расположить их определение в конструкторе, где они будут изготовлены 1 раз, а само описание в свойствах, что бы был доступ к ним из методов. То есть при создании объекта будут созданы все объекты которые потом просто использовать в рамках своей работы. Таким образом при создание виджета будут созданны дочерние объекты а при удаление виджета эти объекты будут удалены автоматически. Для работы с объектами которые непосредственно создаются и уничтожаются в рамках одной функции лучше применять структуры. Следует помнить что создание и удаление объектов - медленный операции. При создание и удаление объектов происходит работа с памятью как в D так и в C++. Это значительно замедляет работу. По этому в функциях требующих максимального быстродействия (Paint), следует применять только предварительно созданные объекты или структуры.

Интересное наблюдение. После исследования похожих библиотек таких как Делфи, PyQt и других, я вижу что оказывается я изобрел велосипед. Разница только в том каким образом осуществить объвязку C++ функции Dшной. Дл Python написана специальная программа которая генерит обвязки для каждой функции Qt. Называется SIPP (кажется). При этом она разбирает исходный текст C++ Qt и генерит нужные обвязки автоматически. Таким образом данная работа автоматизирована частично, но всё-таки автоматизирована. По этому PyQt самая полная. Lazarus пошли другим путем, более похожим на мой. Они руками переписали часть функций Qt (Qt-4) в каком то количестве и они пытаются описать частичные методы и свойства тех объектов Qt, которые им нужны более всего.

Хорошо бы, написать какой-нибудь инструмент, который позволял бы хотя бы частично реализовывать обертки, так как они в принципе однотипные. Есть несколько вариантов обертки для C++ класса в зависимости от некоторых моментов. Большинство обычных функций описывается довольно просто и однотипно. Возможно следующий шаг это написание какого либо инструмента для полуавтоматической генерации данных описаний. Основное отличие моей библиотеки от Lazarus заключается в том, что у меня более приближенно моделируется работа с системой слот - сигнал. В Lazarus вся работа осуществляется строго на событиях. У меня можно использовать как события, так и Signal Slot, что позволяет более просто изучать Qt, читая примеры C++. Пример C++, на 90% может быть положен на QtE5, причём сохраняются все описания вызовов связки слотов и сигналов.

По правильному СИП можно настроить на генерацию любых оберток С++. Сам СИП постоянно обновляется вслед за Qt. Сейчас СИП последней версии может работать с qt5. Возможно если приложить усилия по пониманию работы СИП то через него можно написать обертки для Qt-5 D. Однако Это довольно большой труд. На мой взгляд намного проще сделать более простую распознавалку не C++ Qt, а например описание из HTML документов в интернете. Там же в принципе описаны все вызовы и параметры функции и нас читать C++ текст совсем не обязательно, достаточно просто прочитать описание или выделить функцию, выделить его параметры и автоматически сгенерировать какой то шаблон для вставки в нашу библиотеку.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: