Pull to refresh

Comments 39

А какой лицензией Qt вы пользуетесь?
О, вспомнилась молодость, когда-то очень давно занимался похожими проектами :).
Сейчас правда QWidget — устаревший подход. Посмотрите в сторону QML, он гораздо интереснее. У меня он «зашел» далеко не с первой попытки, но когда я пересилил привычки и освоился то в полной мере оценил его выдающиеся достоинства.
Виджеты вполне удовлетворяют требованиям «под десктоп» и при необходимости достаточно легко кастомизуются/стилизуются и адаптируются под современный, простите, свистопердящий интерфейс. Никто из digia не нарекал их устаревшими.
QML же больше для игр, мобилок и встраиваемых систем.
На QML разработка и поддержка сильно упрощаются. Что совсем неочевидно при чтении документации, но когда начинаешь работать — там очень натурально и легко получается хороший MVC. Нет, виджеты конечно тоже работают, по-прежнему удобны, и на них 90% старых разработчиков сидит. Но новые приложения на них имхо смысла нет делать. Не только для мобилок но и для самого что ни на есть классического десктопа. Тем более что за мобилками в том или ином виде будущеее да и новые вкусные технологии типа того же webgl streaming в виджетах не поддерживаются.
Зря вы так. Это просто консерватизм. Всё совсем наоборот. Плюс вы забываете, что там даже кастомные виджеты писать даже удобнее. ( на том же С++ кстати)
Сделал 5 полноценных проектов в связки QML/Qt за последние лет 7. И в конце каждого проекта понимал, что лучше бы сделал на чистом Qt. Код для связки Qt и QML получается слишком большой. Быстро надоедает его писать.
Никто и не говорил что в MVC кода меньше чем в условном «монолите», особенно со спагетти-кодом. Но если это поддеживать и развивать дальше планируется то затраты на организацию быстро окупаются.
затраты на организацию быстро окупаются

Мой опыт показывает об обратном. Постоянно упираться в «ой а на QML так делать не получится» при реализации специфичных штук. Затраты меньше только на код, относящийся к GUI, но приложение гуи кодом не ограничивается. Интеграция с нативной частью почти всегда уже сжирает все преимущества, когда у вас 30-50к строк на QML.
Qt весь построен вокруг сигналов и слотов (при правильной реализации, а не когда от QThread наследуются и переопределяют run() ). Все сигналы и слоты абсолютно прозрачно пробрасываются в QML. Где конкретно возникает проблема? Что конкретно нельзя делать на QML?
Я не говорю что что-то совсем нельзя сделать на QML. Делаешь нативную часть, к ней обвязку, и тп. я про то что выгода очевидная от QML заканчивается довольно быстро. А потом этого монстра еще и поддерживать)
По-моему все с точностью до наоборот :). На виджетах набросать прототип может быть быстрее, но QML заставляет написать код правильно, так что его в дальнейшем легко поддерживать.
В том-то и дело, что сначала кажется, что кода мало. А потом он начинает плодится и занимать % 20 от всего проекта. Да, в начале проекта QML позволяет быстро сделать красивую картинку, но с ростом проекта выгода от него начинает уменьшаться. В результате начинаешь думать, что лучше бы потратил время на написание собственных контролов в Qt в начале проекта.
QML тоже нужно уметь готовить в том плане, что лучше на нем в начале написать некую продуманную библиотечку «своих» контролов (если не хватает стандартных — скажем, QQC), чем по-быстрому накидать лапшу из примитивов (на лапше из примитивов «красивая картинка» делается быстро, это да), а потом эту лапшу плодить. Ну или если видишь, что начинает плодиться лапша, лучше вовремя сделать рефакторинг, вынести дублирующийся код в местную библиотечку компонентов, продумать его интерфейс. QML тоже вполне модульный, этим можно и нужно пользоваться для уменьшения количества кода.
QML идеально приспособлен для написания собственных контролов.
Я серьезно. Набросать на QML кастомный компонент легче чем сделать кастомный виджет. Я в своих проектах кучу кастомных контролов так сооружаю, даже если типовой контрол — всего лишь специальным образом оформленная кнопочка используемая в четырех местах. Делается-то это тривиально и быстро, поэтому не жалко потратить чуть-чуть времени чтобы убрать копипасту.
Набросать на QML кастомный компонент легче чем сделать кастомный виджет.

+1. Причем намнооого легче.
Полностью согласен. Писать легко, контролы получаются красивыми и быстрыми, минимум кода. Именно это и подкупает в начале проекта. Но связка Qt с QML в итоге занимает много кода и времени. Возможно если всю логику проекта перегнать на сторону QML (под JS) это будет большой проблемой. Но когда логика на C++, а на QML только интерфейс, то для меня это проблема.
Связка Qt с QML идет через сигналы и слоты, что, вообще говоря, и для чисто нативного кода является наиболее «Qt-style» способом общения между собой разных частей приложения. В чем проблема-то? Может я что-то упускаю?
Сигналы/слоты, это если у вас только клавиши. Как только появляются поля ввода, то начинаются свойства, с процедурами чтения/установки и т.д. А если нужно передавать список или таблицу, то программного кода получается очень много. В результате на каждую сущность нужно городить модель. И в конце проекта получается этих моделей штук 20-30, иногда больше.

Модели точно так же надо и для виджетов делать. Для тривиальных вариантов типа списка строк есть стандартные модели.

Имхо вы либо не правильно «варите» Qt, либо что-то не так делаете. Т.к. и в виджетах модели делать надо, делегаты делать надо и прочее. Это ключевой момент отделения UI от логики. Если приложение спроектировано нормально, то перевод на QML с виджетов — тривиальная задача… Да хоть в консоль, хоть вынести UI в веб. QtQuick к этому и приучает.
Простой пример. Есть приложение. В приложении есть некоторые настройки. Эти настройки редактируются на отдельной форме. Требуемое поведение: после изменения настроек проверить их совместимость между собой и в случае отсутствия ошибок применить эти настройки для приложения (пока редактируются настройки, приложение работает на старых настройках). В случае ошибок совместимости настройки не применяются (к примеру, выдается сообщение об ошибках, и форма не закрывается). После изменения, настройки сохраняются, к примеру, в файл для восстановления при следующем запуске приложения.

Как я это делаю на чистом Qt. Панель диалога, при инициализации собираются настройки и заполняются соответствующие контролы. При Accept'е формы данные с контролов читаются, проверяются, если все Ок, то данные записываются в текущие настройки приложения, вызывается метод записи текущих настроек в файл.

Как я это делаю в связке Qt/QML. На Qt пишется модель настроек, причем в этом же классе появляются методы: чтение текущих настроек в модель, проверка настроек, применение настроек (запись в текущие настройки + запись в файл). Эта модель экспортируется в подсистему QML. Делается QML форма. В ней контролы bind'ятся на данные модели, в методе onComplete вызывается метод чтения текущих настроек в модель, на клавишу Ok вешается JavaScript код, который вызывает связку проверки и применения настроек.

Итого: в связке Qt/QML появляется лишний класс модели, который по факту ничего не делает. А если настроек много, то кода получается тоже много (на каждое поле настроек по три метода).
Почему лишняя то? У вас ошибка в проектировании видимо. В нормальной реализации настройками оперирует отдельный класс ( доступ к текущим настройкам, сохранение в файл, загрузка, применение настроек, проверка валидации при применении ). Это и есть ваша модель. Как ваши виджеты, так и QML форма обращается именно к этому классу. Это и есть модель настроек. Разве я не прав?
Тем более к этому же классу можно через сигналы слоты подконнектить все элементы, требующие обновления при изменении той или иной настройки. Всё очень удобно.
Одно из условий — в процессе редактирования приложение использует старые настройки. В той схеме, что вы описали, нельзя будет bind'ить контролы на свойства модели, иначе в процессе редактирование настройки приложения будут меняться (после изменения состояния отдельного контрола). Поэтому и получается «лишний» класс.
Тривиально можно, просто два instance одного класса создайте и все. Один — текущие настройки, другой — настройки в процессе редактирования. С копированием одного в другое по accept. Если же ну очень хочется обойтись вместо модели некоей кашей парсящей содержимое диалога, то есть такой класс как QVariantMap. Он биндится на JS object (по сути — словарь), так что при желании можно все данные из формы писать в единственный объект и читать дальше этот объект как QVariantMap из плюсов.

Или еще проще — пишем функцию setSettings(x,y,z,....), делаем ее Q_INVOKABLE и просто зовем эту функцию в button.onClick, собирая необходимые аргументы
Два экземпляра класса — проблема будет при присвоении, никто автоматически вызывать нотификацию об изменении полей не будет, писать руками — опять лишний код.

Вариант с setParam иногда использовал, но тогда пропадает одна из основных фишек QML — bind'инг.

Оператор копирования написать и все. Там уже должны быть методы setX() кидающие нужные нотификации при их вызове, достаточно просто их позвать. Или сделать на весь класс настроек одну нотификацию settingsChanged вместо нескольких отдельных на каждый элемент класса. Вариантов масса.


В варианте с setParam Вы так и так не используете преимущества биндинга, так что невелика потеря

Не совсем. Биндинг делайте односторонним. Т.е. ты биндишь гую текущие настройки, а не обоюдный биндинг. Т.е. отображаешь то что считал с модели. Когда ты меняешь эти параматры в форме, то они не применяются, биндинг срывается т.к. ты присваиваешь значение именно в форме (гую), а по завершении редактирование применяешь эти настройки т.е. всовываешь в модель по кнопке "сохранить". И всего делов… причем там же идёт проверка валидности.

Посмотрите в сторону QML, он гораздо интереснее.

Для поиграться может и поинтереснее, а для долгоиграющего проекта лучше начинать писать на виджетах. Все реализовать на QML нельзя, как только начинается интеграция нативного кода, сложность быстро растет.
Хотя да, какой-нибудь там автомат по продаже пирожков и газировки на QML делать самое то)
А что конкретно там растет и не может быть реализовано? Я пока с таким не сталкивался, поделитесь опытом. Нативный код абсолютно прозрачно доступен из QML через штатные сигналы и слоты.
Ну например… первое что вспомнил — подскажите, как в QML отобразить произвольный форматированный текст (пришедший с веба например), в качестве надписи? В частности, часть текста подсветить красным. Заранее фрагмент, разумеется неизвестен.
Я вот не нашел способа это сделать)
Берем QML, помещаем туда компонент Text
Берем QObject который отображает нативный функционал в QML, добавляем ему слот в который приложение будет помещать полученный из веба текст:
Q_PROPERTY(QString myText READ myText NOTIFY myTextChanged)

Биндим в QML его со свойством text нашего QML-объекта Text
Text {
    text: cppInterface.myText    
}

И вроде бы на этом всё :). Нам приходит из веба текст, нативный код говорит emit myTextChanged, QML запрашивает строку у нативного кода в геттере myText() и отображает ее. Поддерживаемое форматирование — HTML и CSS. Пример выделения одного слова красным цветом
Hello <span style="font-color:red">world</span> in HTML

Передаем подобную строку в text — она отобразится с выделением слова world красным цветом.
По-моему тут от виджетов каких-то принципиальных отличий нету
Спасибо что так все подробно расписали, в этом не было необходимости :) Я знаю как прокидывать разное, речь как раз про ограниченность текста:
отличие принципиальное одно — указанный вами пример не работает.
Не будет он ничего подсвечивать красным. Только что перепроверил с Qt 5.11, ну вдруг меня память подвела и я что-то там не попробовал.
Я конечно понимаю что вы высокого мнения о себе, но эти комментарии, вообще-то, не только вы читаете. Как сформулировали вопрос — такой и получили ответ.

Не будет он ничего подсвечивать красным.

Ну если тупо копипастить не включая голову то да, «Qt работать» не будет. Чтобы заработало надо в компоненте Text дописать

textFormat: text.RichText

и в HTML использовать не font-color а просто color:
Hello <span style="color:red">world</span> in HTML

Все естественно прекрасно работает. Пруф (Qt 5.12):



Отдельно доставляет то что вы мне заявляли что «подробно расписывать не было необходимости». По всей видимости я как раз недостаточно подробно все для вас разжевал :).
Ладно, был неправ (интересно что с этим же вопросом на форуме Qt мне сказали что это работать не будет, видимо тоже не знали про RichText).
Это лишь одно из препятствий, с которым пришлось столкнуться. Лично мое мнение — перспектив для десктопного применения технология QML не несёт.

Ну я бы сказал что не на форумах надо вопросы задавать а RTFM — в доках по всё это подробно написано, я же не их космоса о RichText узнал. Десять минут на чтение доков и эксперименты и все. В виджетах же ровно та же особенность, в QT работа с текстом и стилями унифицирована. Или фишка в том что виджеты больше народу использует и на форумах лагче найти совет?

Я не против QML, но пока что для разработки десктопных приложений виджеты, себя полностью оправдывают, не тенет переходить на QML. И для данной темы(плагины) всё таки виджеты подходят больше.
А в плане интереса то в QML больше заинтересовало возможность работы с 3D моделями и их интеграция из других IDE.

Для десктопа да, виджеты вполне норм. Но для мобильной и embedded разработки QML лучше. Я, когда QML только появился, тоже сначала с неохотой на него переползал, но потом разобрался, проникся и пользую с удовольствием.

Sign up to leave a comment.

Articles