Страницы

Поиск по вопросам

Показаны сообщения с ярлыком qml. Показать все сообщения
Показаны сообщения с ярлыком qml. Показать все сообщения

суббота, 11 апреля 2020 г.

Как должны правильно взаимодействовать модель и QSortFilterProxyModel?

#cpp #qt #qt5 #qml

                    
Приветствую! 
Ситуация следующая:
Есть моделька, основанная на QAbstractItemModel, так как данных достаточно много,
получаю их с помощью предназначенного для этого canFetchMore и fetchMore
и когда просто модель отображается в ListView (qml), всё замечательно, данные подгружаются
по мере пролистывания.

Теперь на эту модельку сверху вешаю прокси, на основе QSortFilterProxyModel
в ней для теста отбираю строки (переопределив filterAcceptsRow) по какому нибудь
полю, не важно. 

Дальше начинаются проблемы. 
При установленной фильтрации во вьюшке выводятся не все возможные значения!
т.е. выводятся только загруженные в fetchMore в данный момент. 
Т.е. в fetchMore гружу по 100 записей, не выводятся ни одной, т.к. целевые значения
будут прогружены начиная с 500.
и прогрузки дальше не происходит т.к. логично, что вьюшка не считает необходимым
загружать ещё т.к. всё умещается и не надо пролистывать но и прокси моделька не считает
нужным прогрузить дальше, либо как-то сообщить основной модели - мне нужны записи с
вот такими значениями.

Подскажите, пожалуйста, как быть? 
Не, я согласен, что лучше всего будет выбирать нужные значение через запрос к базе,
что бы не грузить лишнего,
но как тогда лучше сделать связь с основной моделью? 

т.е. например я в fetchRow основной модели прогрузил записи от 0 до 100, в прокси
модели нужно выбирать, которые располагаются начиная с 500, ок, я говорю основной модели
- прогрузи ка записи с вот такими значенияи, если есть.
Ок, гружу. 

Но возникает следующая проблема - если запись например 555 добавлена в модель, то
при скролинге вьюшки, она попросит записи с 500 по 600 и я тогда снова добавлю запись
555. т.е. получается будет дублирование. 
Запоминать записи, которые грузил? что-то костылём попахивает. 
Может есть красивый выход из ситуации?

Спасибо, даже за подсказки, на что смотреть!
    


Ответы

Ответ 1



На мой взгляд, тут может быть только три варианта для решения проблемы. Первый - самый бестолковый, если данных очень много. Предполагает, что модель-источник должна загрузить сразу все данные и не использовать fetchMore в принципе. Второе решение может быть основано на переопределении метода fetchMore() у прокси с тем условием, что будет сразу же (рекурсивно) повторять запрос на чтение новых строк из исходной модели до тех пор, пока количество строк в прокси после filterAcceptsRow() не достигнет нужного числа, либо исходная модель не прочитает все данные. Фактически, это решение почти столь же бестолковое, что и первое, так как потребуется полное считывание всех данных исходной модели при определённых условиях фильтрации. Третье решение предполагает использование фильтрации данных непосредственно в модели-источнике. Обратите внимание, что все SQL-модели из состава Qt имеют возможность фильтровать данные самостоятельно и в общем случае не нуждаются в каких-либо прокси. Если модель-источник является таблицей в БД, то имеет смысл использовать классы, специально предназначенные для работы с подобными источниками, а не заниматься наследованием абстрактной модели. Если же модель-источник не является таблицей в БД, а, например, представляет из себя некий файл, то фильтрация данных должна быть добавлена в эту исходную модель и производиться непосредственно при вызове fetchMore() с тем, чтобы выдать минимальное количество данных, соответствующих условиям фильтрации.

четверг, 19 марта 2020 г.

QML vs QPainter Widget - что производительнее?

#widgets #qt #cpp #qml


Собираясь разрабатывать новое приложение (на C++ и Qt), столкнулся перед выбором:
как реализовать интерфейс - на QML или сделать по старинке виджетами (будет виджет,
наследованный от QPainter на котором будут отрисовываться объекты да скроллироваться,
и еще несколько виджетов с различными текстовыми полями и кнопками). С QML у меня нет
никакого опыта, поэтому на виджетах я сделаю интерфейс намного быстрее. Однако, может
быть у QML есть какие-то плюсы по сравнению с традиционными виджетами? Так какие же?
Что из них производительнее?    


Ответы

Ответ 1



Вы пытаетесь сравнивать кислое с синим. Вот скажите мне, например, что производительнее - XML или Frostbite 2? QML - это удобный способ программировать виджеты, транзишны, разнообразные визуальные эффекты и стили оформления. Он парсится как язык, но в конечном счете отрисовывает то, что вы ему сообщили, с помощью того же самого QPainter'a: QML builds directly upon QGraphicsView, which in turn builds upon QPainter, which in turn builds upon QPaintEngine (and the internal QGraphicsSystem classes), which have various hardware accelerated implementations. Утверждается, что любой случай сложной разметки и логики на QML можно проэмулировать, вручную создавая элементы на QGraphicsView, и, соответственно, получить абсолютно одинаковую производительность.

Ответ 2



Вот, что мне ответили на Хабре: Насчёт производительности — разница только на старте, когда грузится и парсится QML. Далее на его основе создаются обычные «плюсовые» объекты в памяти, так что во время исполнения разницы не будет. А если ваш QML не супер-дупер навороченный, то вы и во время загрузки разницы не ощутите. Плюсы у QML — более компактное, более читабельное описание интерфейса, а также тот факт, что тенденция развития Qt однозначно идёт к QML. В Qt5 вроде бы от нативных виджетов понемногу отходят (тут врать не буду, возможно неправ).

среда, 1 января 2020 г.

Как снизить использование памяти QQuickWidget'а

#qt5 #qml


Не пойму, почему так много расходится память для отображения qml файла. Вот скриншот:



Вот код:

C++

#include 
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QQuickWidget widget;
    widget.setSource(QUrl::fromLocalFile("text.qml"));
    widget.setWindowFlag(Qt::FramelessWindowHint);
    widget.show();

    return a.exec();
}


text.qml:

import QtQuick 2.12
Item
{
    width: 150
    height: 200

    Rectangle
    {
        width: parent.width
        height: parent.height
        color: "#66ff99"
    }

}


Почему для отображения простого прямоугольника, нужно столько памяти?
    


Ответы

Ответ 1



Так же можно утсановить вот этот флаг, который снижает потребеление памяти в 5 раз. QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software); Беспонятие, что этот флаг значит, но работает он бесподобно.

Ответ 2



QML - наследник программного инструмента QtScript, который в свою очередь реализует полноценный JavaScript интерпритатор со своим Garbage Collector, глобальными объектами (например, XMLHttpRequest, который доступен как в js, так и qml), а так же механизмами прототипного наследования. То, что суммарно программа потребляет так много памяти это норма в 2019 году... Теоретически, можно обнулить какие-то части глобального объекта QML. В принципе, если вам не нужны HTTP запросы прямо с QML разметки. На практике - 100+ мегабайт это совершенно нормальное потребление памяти для приложения, которое взаимодействует с API целевой операционной системы через абстракцию. #include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickView view; view.setSource(QUrl::fromLocalFile("application.qml")); view.show(); return app.exec(); } P.S. Если приложение использует только функциональность QML, возможно, применение класса QGuiApplication вместо QApplication поможет сэкономить память.

вторник, 16 июля 2019 г.

Как убрать скроллбар из TableView QML?

Добрый день! Собственно, вопрос из темы: Как убрать скроллбар из TableView? Я новичок и документация с гуглом мне не помогли.


Ответ

verticalScrollBarPolicy отвечает за политику отображения http://doc.qt.io/qt-5/qml-qtquick-controls-scrollview.html#verticalScrollBarPolicy-prop
TableView { verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff }

вторник, 11 июня 2019 г.

Изменение текстового поля на форме из потока (2 окна) QML QT C++

Пытаюсь изменить значение текстового поля из другого потока, но почему-то не работает: Есть 2 окна, первое окно:
firstwindow.h:
#include "mythread.h" #include
class FirstWindow : public QObject { Q_OBJECT public: explicit FirstWindow(QObject *parent = nullptr); private: MyThread *myThread; public slots: void start(); };
firstwindow.cpp:
#include "firstwindow.h"
FirstWindow::FirstWindow(QObject *parent) : QObject(parent) {
}
void FirstWindow::start() { myThread = new MyThread(5); //передача значения в класс MyThread }
firstwindow.qml:
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 import QtQuick.Window 2.0
import FirstWindowModule 1.0
ApplicationWindow { visible: true width: 380 height: 240 id: firstwindow
FirstWindow { id: obj; }
//создание и вызов второго окна, вызов функции start(), создающей объект класса MyThread Button { text: "Start" onClicked: {
var component = Qt.createComponent("main.qml"); console.log("Component Status:", component.status, component.errorString()); var window = component.createObject(firstwindow); window.show()
obj.start(); } } }
Второе окно:
mythread.h:
#include "newclass.h" #include #include
class MyThread : public QObject { Q_OBJECT Q_PROPERTY(QString firstNumber READ GetFirstNumber WRITE SetFirstNumber NOTIFY firstNumberChanged)
private: QThread *thread; NewClass *newClass; QString firstNumber; int counter;
private slots: void UpdateFirstValue (int i); public slots: void StartThread(int); public: explicit MyThread(int value, QObject *parent = nullptr); explicit MyThread(QObject *parent = nullptr); QString GetFirstNumber(); void SetFirstNumber(QString);
signals: void firstNumberChanged(); };
mythread.cpp:
#include "mythread.h"
MyThread::MyThread(QObject *parent) : QObject(parent) { }
MyThread::MyThread(int counter, QObject *parent) : QObject(parent) { this->counter = counter; StartThread(counter); //запуск функции создания и запуска потока }
QString MyThread::GetFirstNumber() { return firstNumber; }
void MyThread::SetFirstNumber(QString value) { firstNumber = value; }
void MyThread::StartThread(int counter) { thread = new QThread; newClass = new NewClass(counter); newClass->moveToThread(thread);
connect(newClass, SIGNAL(sendfirstvalue(int)), this, SLOT(UpdateFirstValue(int))); connect(thread, SIGNAL(started()), newClass, SLOT(Start())); thread->start(); }
void MyThread::UpdateFirstValue (int i) { firstNumber = QString::number(i); emit firstNumberChanged(); }
main.qml:
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 import QtQuick.Window 2.0
import NameModule 1.0
ApplicationWindow { visible: true width: 380 height: 240
Rectangle { id: content
TypeName { id: obj }
ColumnLayout { height: parent.height anchors.horizontalCenter: content.horizontalCenter Rectangle { Layout.fillHeight: true Text { anchors.centerIn: parent id: firstNumber text: "f = " + obj.firstNumber font.bold: true
onTextChanged: { console.log("firstNumberChanged"); }
} } } } }
Класс NewClass, функция которого работает в потоке:
newclass.h:
#include
class NewClass : public QObject { Q_OBJECT
public: explicit NewClass(int value, QObject *parent = nullptr); signals: void sendfirstvalue(int); private slots: void Start(); private: int value; };
newclass.cpp:
#include "newclass.h" #include #include "QDebug"
NewClass::NewClass(int value, QObject *parent) : QObject(parent) { this->value = value; }
void NewClass::Start() { qDebug() << "value" << value; for(int i = 0; i < value; i++) { qDebug() << "i" << i; emit sendfirstvalue(i); Sleep(1000); // from windows.h } }
Связка классов FirstWindow и MyThread с соответствующими им qml:
qmlRegisterType("FirstWindowModule", 1, 0, "FirstWindow"); qmlRegisterType("NameModule", 1, 0, "TypeName");
Суть проблемы: 2 окна, в первом окне (FirstWindow) располагается кнопка, по которой открывается второе окно (MyThread), и сразу запускается вычислительный процесс в новом потоке (функция Start() в классе NewClass. Данная функция в цикле, каждую секунду отсылает целочисленное значение обратно во второе окно MyThread, и данное значение должно отображаться в данном окне. Установлено, что проблема скорее всего в создании этого второго окна, что либо поток запускается раньше, чем показывается окно, либо еще что-то. Спасибо.
UPDATE: заново переписал вопрос и залил проект на https://github.com/sawyerhard/test2, Проблема не решена


Ответ

Проблема решена) В общем вся проблема была в этих 2х строчках в файле firstwindow.qml:
var window = component.createObject(firstwindow);
и вызов функции
obj.start();
при котором происходило повторное!!! создание объекта myThread, так как основной объект создавался в строчке выше (так как окно связано с MyThread классом), из-за этого данные, которые хоть и приходили, но не отображались в окне.
Решение: 1. Убираем строчку из firstwindow.qml:
obj.start();
2. Добавляем метод onCompleted в файл main.qml, в котором запускаем выполнение потока:
Component.onCompleted: { obj.startThread(5); }
Всем спасибо)

четверг, 6 июня 2019 г.

QML vs QPainter Widget - что производительнее?

Собираясь разрабатывать новое приложение (на C++ и Qt), столкнулся перед выбором: как реализовать интерфейс - на QML или сделать по старинке виджетами (будет виджет, наследованный от QPainter на котором будут отрисовываться объекты да скроллироваться, и еще несколько виджетов с различными текстовыми полями и кнопками). С QML у меня нет никакого опыта, поэтому на виджетах я сделаю интерфейс намного быстрее. Однако, может быть у QML есть какие-то плюсы по сравнению с традиционными виджетами? Так какие же? Что из них производительнее?


Ответ

Вы пытаетесь сравнивать кислое с синим. Вот скажите мне, например, что производительнее - XML или Frostbite 2? QML - это удобный способ программировать виджеты, транзишны, разнообразные визуальные эффекты и стили оформления. Он парсится как язык, но в конечном счете отрисовывает то, что вы ему сообщили, с помощью того же самого QPainter'a: QML builds directly upon QGraphicsView, which in turn builds upon QPainter, which in turn builds upon QPaintEngine (and the internal QGraphicsSystem classes), which have various hardware accelerated implementations. Утверждается, что любой случай сложной разметки и логики на QML можно проэмулировать, вручную создавая элементы на QGraphicsView, и, соответственно, получить абсолютно одинаковую производительность.