Russian Qt Forum
Апрель 20, 2024, 02:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как быстро сграббить Item в картинку при его изменении?  (Прочитано 2982 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« : Декабрь 12, 2017, 16:41 »

Всем привет.

Когда то давно поднимал тему о том, как сграббить содержимое виджета
в картинку при изменении его содержимого, и мне помог Igors, примерно
с таким кодом:

Код
C++ (Qt)
bool MyWidget::event(QEvent *event)
{
   if (event->type() == QEvent::UpdateRequest)
       myGrab();
   return QWidget::event(event);
}
 
void MyWidget::myGrab()
{
   ...
   QBackingStore *store = backingStore();
   Q_ASSERT(store);
 
   QPaintDevice *pdev = store->paintDevice();
   const auto image = dynamic_cast<QImage *>(pdev);
   ...
}
 

Но теперь встала аналогичная задача с QML, нужно сграббить Item со всем его содержимым
в картинку каждый раз при его изменении. На LOR-е подсказали примерный код, который я немного подправил:

Код
C++ (Qt)
Grabber::Grabber(QQuickItem *parent)
   : QQuickItem(parent)
{
   setFlag(QQuickItem::ItemHasContents);
}
 
// Where sourceItem - is a watched item.
void Grabber::setSourceItem(QQuickItem *sourceItem)
{
   if (sourceItem == m_sourceItem)
       return;
   m_sourceItem = sourceItem;
   emit sourceItemChanged(m_sourceItem);
   update();
}
 
QSGNode *Grabber::updatePaintNode(QSGNode *oldNode,
                                 UpdatePaintNodeData *updatePaintNodeData)
{
   Q_UNUSED(updatePaintNodeData);
 
   if (!m_sourceItem)
       return oldNode;
 
   QSGRootNode root;
   root.appendChildNode(QQuickItemPrivate::get(m_sourceItem)->itemNode());
 
   const QScopedPointer<QSGRenderer> renderer(
               QQuickItemPrivate::get(this)->
               sceneGraphRenderContext()->createRenderer());
 
   renderer->setRootNode(&root);
 
   const QSize size(m_sourceItem->width(), m_sourceItem->height());
   renderer->setDeviceRect(size);
   renderer->setViewportRect(size);
   renderer->setProjectionMatrixToRect(QRectF(QPointF(), size));
   renderer->setClearColor(Qt::transparent);
 
   QOpenGLFramebufferObject fbo(size);
   renderer->renderScene(BindableFbo(&fbo));
   fbo.release();
 
   QElapsedTimer et;
   et.start();
   const QImage image = fbo.toImage(); // TOO LONG ~24 msec!
   qDebug() << "Elapsed:" << et.elapsed();
 
   return oldNode;
}
 

но тут два косяка:

1. Оочень медленно работает fbo.toImage() - около 24 миллисекунд для 800х600
(и где хваленое OpenGL??).
2. Непонятно как узнать момент перерисовки содержимого отслеживаемого Item,
у него нету ну никаких сигналов.

Ппц, я уже закипел как чайник.. Грустный
« Последнее редактирование: Декабрь 12, 2017, 16:43 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #1 : Декабрь 13, 2017, 09:16 »

В итоге набросал на коленке такой код, но все-равно, кажется, что это какой-то костыль убогий и тормозной. Грустный
Записан

ArchLinux x86_64 / Win10 64 bit
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.088 секунд. Запросов: 22.