Название: [РЕШЕНО] Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 17, 2019, 23:07 Нужно сделать скроллируемый декорированный список строк с чекбоксами, и обязательно внутри QGraphicsScene - чтобы легко масштабировать под разные размеры экрана в Android. Всегда всё делал на виджетах. Но QListView и QListWidget с добавленными к ним виджетами не работают в QGraphicsScene. На эту тему уже есть баг репорт. Заранее просьба - не предлагать реализовать через делегатов для QListView. Я пробовал, получается такая мешанина, что это в только самом крайнем случае. В реальной задаче в элементе списка должны быть 12 текстовых полей с разными размерами шрифтов, и два чекбокса. Количество элементов списка в реальности до 150, но размер каждого элемента должен быть 200 пикселов, чтобы все поля поместились. И должны быть три разных варианта отображения с разными расположениями и размерами текстов. На QML это сделать было бы милое дело...
Поэтому попытался сделать на QML с помощью ListView и делегата, засунув их в QQuickWidget, а его уже в QGraphicsScene. При этом в QML я как свинья в апельсинах, то есть почти никак. Сначала вроде с помощью Интернет всё получилось - и список легко декорирован, и чекбокс без проблем, и текст на строках можно расположить где угодно и разного размера. То, что мне надо. Но потом... когда увеличил количество элементов в списке, вдруг обнаружил что вместо него в окне чёрное поле с какими-то графическими искажениями. И в консоли появились сообщения об ошибке: Цитировать QOpenGLFramebufferObject: Framebuffer incomplete attachment. QOpenGLFramebufferObject: Framebuffer incomplete attachment. QOpenGLFramebufferObject: Framebuffer incomplete attachment. QOpenGLFramebufferObject: Framebuffer incomplete attachment. QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment. С меньшим числом элементов списка их не было. Экспериментально установил, что всё это начинается если вертикальный размер изображения списка превышает 4096 пикселов. До 4096 всё работает, но с 4097 уже нет. Пытаюсь найти соответствующее описание где-нибудь - ничего не нахожу. Нашёл только близкую по теме проблему у одного разработчика на stackoverflow (https://stackoverflow.com/questions/46032180/qml-take-screenshot-of-the-whole-listviewincluding-the-clipped-part). Больше нигде никаких упоминаний о каких-либо ограничениях. Прикладываю здесь исходник тестового приложения, компилировал и проверял в десктопном Linux с Qt 5.9. Изначально всё работает. Но если в начале файла testlist.cpp закомментировать первую строчку с #define works - после пересборки вместо красивого скроллирующего списка в окне будет какая-то хрень. Это увеличивает вертикальный размер элемента списка с 40 пикселов до 50, весь список получается 5000 пикселов вместо 4000, и оба-на. Кто-нибудь слышал что-нибудь об этой проблеме? Есть какие-нибудь пути её обхода? Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: kambala от Апрель 18, 2019, 01:08 Qt 5.12.2, macOS 10.13.6 — никаких проблем что с works, что без.
Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 03:01 О. Вот это надо проверить с Qt 5.12. ОС тут вряд ли имеет значение. Хотя... для рендеринга используется OpenGL, могут быть нюансы.
А если число элементов задать 150, а высоту каждого 200? Это соответственно const int num в методе TestList::FillList() и число в открытой ветке #ifdef works ниже. Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: kambala от Апрель 18, 2019, 03:24 в этом случае наблюдаю ту же проблему, что и у тебя. но при количестве 150 и высоте 50 проблем нет.
Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: qate от Апрель 18, 2019, 09:14 Надо запилить багрепорт - даже пример есть !
Я решил еще раз попробовать qml т.к. может придется сделать простое приложение, но чтобы работало и на андроиде и на десктопе. Кроме Qml решения не вижу чтобы дважды не писать И очень мало кто использует qml по сравнению в виджетами - чтото найти сложно, а сразу много непонятно ) Например при сборке и установке на андроит qt либы всегда помещаются в apk - что тормозит и сборку и запуск, как убрать непонятно. Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 11:09 в этом случае наблюдаю ту же проблему, что и у тебя. но при количестве 150 и высоте 50 проблем нет. Можете установить "границу" - при каком числе вертикальных пикселов ломается? У меня при 4096, это не случайное число - 2^12. Устанавливать приходится методом ловли льва в пустыне - то есть, подбором с половинным делением. Если это тоже степень двойки, то граница будет быстро заметна.Для этого нужно: 1. в файле testlist.cpp заменить строку: setResizeMode(QQuickWidget::SizeRootObjectToView); на setResizeMode(QQuickWidget::SizeViewToRootObject); 2. в нём же закомментировать строки с 32 по 38 включительно 3. в файле main.qml раскомментировать строки 13 и 14 4. в строке 14 менять высоту в пикселах Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 12:11 qate, в вашем сообщении по теме только замечание про баг репорт, всё остальное оффтопик. За мной не убудет, не впервой багрепорты Qt писать - надо только больше материала собрать. По поводу остального - если для Android не требуется делать скроллирующий список со сложными айтемами, которые должны собираться из разных элементов, то всё можно сделать на виджетах. И так что будет одинаково работать на всех ОС, включая Android. Правда, чтобы и выглядело одинаково, придётся все виджеты самостоятельно декорировать, то есть писать в них paintEvent() и рисовать им картинки. У меня таким способом сделано больше 20 приложений на Google Play, и да - они идентично работают в Windows и Linux. По поводу библиотек Qt - изучите Ministro. И просьба больше в этой ветке не оффтопить.
Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: ViTech от Апрель 18, 2019, 12:24 Можете установить "границу" - при каком числе вертикальных пикселов ломается? У меня при 4096, это не случайное число - 2^12. Возможно дело в ограничении на размер текстуры (Maximum OpenGL FrameBuffer Object size limit? (https://stackoverflow.com/questions/6655943/maximum-opengl-framebuffer-object-size-limit)). Соответственно, может не стоит устанавливать размер QQuickWidget больше этих лимитов. Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 12:55 Можете установить "границу" - при каком числе вертикальных пикселов ломается? У меня при 4096, это не случайное число - 2^12. Возможно дело в ограничении на размер текстуры (Maximum OpenGL FrameBuffer Object size limit? (https://stackoverflow.com/questions/6655943/maximum-opengl-framebuffer-object-size-limit)). Соответственно, может не стоит устанавливать размер QQuickWidget больше этих лимитов. Я тоже так сначала думал. Но... если в моём примере раскомментировать в файле main.qml строки, включающие использование QML типа Window (для этого надо ещё раскомментировать строку с anchors.fill parent в ListView) и выполнить шаг 1 из моего предыдущего сообщения, то это не подтверждается! Откроется отдельное окно с размерами, заданными в main.qml, и в нём будет скроллировать весь список, все 100 айтемов. Высота списка в этом случае 5000 пикселов. Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: kambala от Апрель 18, 2019, 12:59 у меня предел 8192. подтвердил это, проверив максимальный размер буфера.
Код
Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: ViTech от Апрель 18, 2019, 14:09 Я тоже так сначала думал. Но... если в моём примере раскомментировать в файле main.qml строки, включающие использование QML типа Window (для этого надо ещё раскомментировать строку с anchors.fill parent в ListView) и выполнить шаг 1 из моего предыдущего сообщения, то это не подтверждается! Откроется отдельное окно с размерами, заданными в main.qml, и в нём будет скроллировать весь список, все 100 айтемов. Высота списка в этом случае 5000 пикселов. А "QML типа Window" и QQuickWidget это одно и то же? Возможно, "QML типа Window" и имеет большие размеры, но, условно говоря, "viewport" для него гораздо меньше, и имеет ограничения по размеру framebuffer. На экране это отдельное окно реально высотой 5000 пикселей? И ошибки "QOpenGLFramebufferObject: Framebuffer incomplete attachment." при этом не появляются? Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 16:30 Я тоже так сначала думал. Но... если в моём примере раскомментировать в файле main.qml строки, включающие использование QML типа Window (для этого надо ещё раскомментировать строку с anchors.fill parent в ListView) и выполнить шаг 1 из моего предыдущего сообщения, то это не подтверждается! Откроется отдельное окно с размерами, заданными в main.qml, и в нём будет скроллировать весь список, все 100 айтемов. Высота списка в этом случае 5000 пикселов. А "QML типа Window" и QQuickWidget это одно и то же? Возможно, "QML типа Window" и имеет большие размеры, но, условно говоря, "viewport" для него гораздо меньше, и имеет ограничения по размеру framebuffer. На экране это отдельное окно реально высотой 5000 пикселей? И ошибки "QOpenGLFramebufferObject: Framebuffer incomplete attachment." при этом не появляются? Нет, на экране это окно с тем размером, который задан в QML Window { width: height: }. Я делал его 600х300. Но в нём скроллирует всё полотно высотой 5000 пикселов, то есть весь мой QQuickWidget. Ошибки при этом не появляются. Значит он отрендерился в OpenGL полностью. Попозже сегодня попробую проверить есть ли в этом случае лимит, сейчас некогда. Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 18:12 Сейчас проверил работу QQuickWidget в окне, заданном в QML, при больших размерах списка. То есть, main.qml выглядит так:
Код: import QtQuick 2.9 В testlist.cpp Код: TestList::TestList(QWidget *p, uint _width) : QQuickWidget(p), width(_width) То есть, размер полотна 33000 пикселов. И нормально оно в отдельном окне скроллирует всё. Но! В консоли сообщения те же сообщения об ошибках, и добавились ещё два: Код: QXcbShmImage: shmget() failed (22: ???????????? ????????) for size 120252000 (911x33000) Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: ViTech от Апрель 18, 2019, 18:28 QQuickWindow и QQuickWidget - найдите 10 отличий :).
Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 18:55 QQuickWindow и QQuickWidget - найдите 10 отличий :). Во-первых, независимо от количества отличий, есть одно совпадение - их содержимое рендерится в OpenGL. Во-вторых, мой TestList - он не стал QQuickWindow. Он так и остался QQuickWidget.Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: ViTech от Апрель 18, 2019, 19:28 Во-вторых, мой TestList - он не стал QQuickWindow. Он так и остался QQuickWidget. Вот именно.Код
А для ListView можно добавить скроллбар (https://stackoverflow.com/questions/45650226/qml-attach-scrollbar-to-listview). Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 19:38 Зачем этот код? Вы его запускали? Я такой вчера делал.
Скроллбар у меня должен быть у QGraphicsScene - и он там есть, если виджет в ограничения размеров не упирается. Отдельное окно мне нафик не нужно. На сцене кроме виджета, ещё кнопки будут и поле для рекламы с AdMob. Чтобы всё это масштабировалось вызовом QGraphicsView::scale(x,y). А с отдельным окном мне делать нечего, есть там скроллбар или нет. Стоп, я тут что-то нащупал... В main.qml надо Window заменить на Item... Название: Re: Странное ограничение размеров QML ListView в QQuickWidget Отправлено: Гурман от Апрель 18, 2019, 20:15 Да. Получилось. Я вчера ходил возле этого решения, но после длительной долбёжки лбом об стенку прозевал его. В реальном приложении всё будет немного не так, но принцип вроде найден. Если это ещё и не будет на Android слишком сильно тормозить с несколькими сотнями айтемов, то похоже то что надо.
|