Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Система рисования. Печать _ Отрисовка стандартного виджета на буфер

Автор: piton 29.9.2009, 13:11

Предисловие: есть движок, в котором реализованы мультимедиа объекты (картинки, видео, текст и т.д.) и их управление (загрузка, отрисовка, размещение на окне). Все объекты выводятся на окно в зависимости от их глубины (depth) размещения, т.е. объекты могут друг на друга наезжать и частично или полностью перекрывать друг друга. Все это дело должно работать как под виндой, так и под линуксами. Было принято решение использовать QT в качестве реализации главного окна и обработки мышиных и клавиатурных сообщений.

Сама суть: нужен ввод с клавиатуры в текстовое поле. В качестве эксперимента был взят класс QTextEdit. В принципе в нем все устраивает, за исключением одного момента: это отрисовка в буфер. Снять копию с виджета и поместить ее в тот же QImage не составляет труда, но нельзя запретить виджету рисоваться куда ему захочется. Под виндой это решалось просто, путем сабклассинга и подсовывание своего контекста рисования. В QT я не нашел способа подсунуть свой контекст для отрисовки. QT настырно продолжает рисовать на свой контекст. Пробовал переопределять функции, связанные с рисованием, но в QT они носят чисто информационный характер, т.е. как состоявшийся факт "я отрисовалась и если хочешь, можешь ты еще чего поверх нарисовать". Цель состоит в том, что бы можно было поле для ввода текста использовать от QT и при этом рисовать самому, перемешивая с другими объектами.

Вопрос: возможно ли запретить виджету рисоваться куда ему захочется или дать виджету свой контекст для рисования и он сам туда рисовался, при этом не использовал контекст рисования родительского окна (фактически единственного окна)?

Автор: rnd 29.9.2009, 14:23

наследуйтесь и переопределите QTextEdit::paintEvent - в нем рисуйте что надо

Автор: piton 29.9.2009, 14:27

Цитата(rnd @ 29.9.2009, 15:23) *
наследуйтесь и переопределите QTextEdit::paintEvent - в нем рисуйте что надо


Пробовал.
Эта функция вызывается когда виджет уже отрисовался и оповещает о случившемся факте.

А надо что бы он вообще не рисовался или рисовался только на определенный (свой) контекст.

Цитата(rnd @ 29.9.2009, 15:23) *
наследуйтесь и переопределите QTextEdit::paintEvent - в нем рисуйте что надо


Пробовал.
Эта функция вызывается когда виджет уже отрисовался и оповещает о случившемся факте.

А надо что бы он вообще не рисовался или рисовался только на определенный (свой) контекст.

Автор: ViGOur 29.9.2009, 15:10

Цитата(piton @ 29.9.2009, 15:27) *
Пробовал.
Эта функция вызывается когда виджет уже отрисовался и оповещает о случившемся факте.
покажи код, которым пробовал нарисовать что-то на виджите!

И еще, читал: http://doc.crossplatform.ru/qt/4.5.0/qt4-arthur.html?

Автор: piton 29.9.2009, 15:42

Цитата(ViGOur @ 29.9.2009, 16:10) *
Цитата(piton @ 29.9.2009, 15:27) *
Пробовал.
Эта функция вызывается когда виджет уже отрисовался и оповещает о случившемся факте.
покажи код, которым пробовал нарисовать что-то на виджите!

И еще, читал: http://doc.crossplatform.ru/qt/4.5.0/qt4-arthur.html?


Читал, не помогло... :(

Мне не надо рисовать на виджете, мне надо что бы он рисовался на моем контексте и больше ни где не рисовался. Рисовать на виджете не сложно и есть куча вариантов как это делать.

Ситуация в следующем состоит: при загрузке QT приложения, создается только одно окно (на примере винды это хорошо видно, если посмотреть при помощи spy++ от вижуальника). В винде под каждый компонент, как правило, создается свое дочернее окно. Т.е. получается, что все объекты в QT рисуются на контекст главного окна. Что бы вклинится в отрисовку надо либо всем объектам наследоваться от QT и создавать на основе QT слоеный пирог на отрисовку, либо найти способ, который позволит заставить виджет рисовать свое содержимое на собственный контекст, а не на контекст главного окна.

Как заставить виджет рисоваться на сторонний контекст и при этом принадлежать главному окну или вообще не рисоваться никогда (в не зависимости от его видимости, при этом грабить его содержимое через grabWidget(...)) мне пока вообще не понятно. Пробовал виджет скрывать, но при этом он не реагирует на любую просьбу нарисоваться. Так же пробовал вывести его за область видимости в самом окне, так там стоит оптимизация, если виджет не видим или его часть, то эта часть просто не рисуется.

Возможно, надо использовать свой класс (наследовать его от QPaintEngine, QPaintDevice), но я так и не нашел способа, что бы скормить виджету его и что бы он рисовал через него.

Автор: Litkevich Yuriy 29.9.2009, 15:46

Цитата(piton @ 29.9.2009, 18:27) *
Эта функция вызывается когда виджет уже отрисовался
нет, только когда он хочет рисоваться.

Ещё можешь почитать http://www.crossplatform.ru/node/887, как мы её окрестили :)

Автор: piton 29.9.2009, 16:15

Цитата(Litkevich Yuriy @ 29.9.2009, 16:46) *
Цитата(piton @ 29.9.2009, 18:27) *
Эта функция вызывается когда виджет уже отрисовался
нет, только когда он хочет рисоваться.

Хорошо.

class myEdit : public QTextEdit
{
public:
  myEdit(QWidget *parent)
    : QTextEdit(parent)
  {
  }

protected:
  virtual void paintEvent(QPaintEvent *event)
  {
    /*
      Тут мы можем что нарисовать, но мне это не нужно
    */

    // Если принять сообщение
    event->accept();
    // то и граб и рендер не будет работать, т.е. это полностью глушит отрисовку

    // Если же вызвать родителя, то виджет смело отрисуется на контекст главного окна.
    QTextEdit::paintEvent(event);
  }
}

Может есть возможность во время paintEvent(...) снимать копию изображения с виджета или говорить ему что надо отрисовать на сторонний контекст?

Цитата(Litkevich Yuriy @ 29.9.2009, 16:46) *
Ещё можешь почитать http://www.crossplatform.ru/node/887, как мы её окрестили :)

Спасибо за пример. Но немного не по моей теме. :unsure: . Может и ошибаюсь....

Автор: Litkevich Yuriy 29.9.2009, 16:27

Цитата(piton @ 29.9.2009, 20:15) *
отрисовать на сторонний контекст?
я честно говоря не совсем понимаю, что значит на сторонний. И что значит на контекст, на чём-то другом кроме экрана?

Если так то можно посмотреть в сторону QImage.

Автор: piton 29.9.2009, 16:54

Цитата(Litkevich Yuriy @ 29.9.2009, 17:27) *
Цитата(piton @ 29.9.2009, 20:15) *
отрисовать на сторонний контекст?
я честно говоря не совсем понимаю, что значит на сторонний. И что значит на контекст, на чём-то другом кроме экрана?

Если так то можно посмотреть в сторону QImage.

В QT все объекты рисуются на главное окно. Мне надо что бы виджет (QTextEdit) рисовался, скажем. на QImage и только на него, что бы виджет не рисовался на главное окно. Я знаю как рисовать на QImage, но при этом видже одновременно рисуется на главное окно. Если его скрывать или убирать за пределы окна, то он тупо перестает рисоваться, даже на QImage.

сторонний - все что угодно, только не главное окно
на контекст - HDC, QImage, QPixmap и т.д.

Автор: BRE 29.9.2009, 17:05

Цитата(piton @ 29.9.2009, 17:54) *
сторонний - все что угодно, только не главное окно
на контекст - HDC, QImage, QPixmap и т.д.

Думаю стоит смотреть в сторону QPaintEngine, и делать своего наследника...

Автор: piton 29.9.2009, 17:16

Цитата(BRE @ 29.9.2009, 18:05) *
Думаю стоит смотреть в сторону QPaintEngine, и делать своего наследника...


Я так и не смог найти какого-либо примера или информации как это можно сделать. Хвостов у виджета в сторону QPaintEngine тоже не обнаружил. :(
Если есть какие либо мысли, с удовольствие выслушаю.

Цитата(BRE @ 29.9.2009, 18:05) *
Думаю стоит смотреть в сторону QPaintEngine, и делать своего наследника...


Я так и не смог найти какого-либо примера или информации как это можно сделать. Хвостов у виджета в сторону QPaintEngine тоже не обнаружил. :(
Если есть какие либо мысли, с удовольствие выслушаю.

Автор: BRE 29.9.2009, 17:23

Цитата(piton @ 29.9.2009, 18:08) *
Я так и не смог найти какого-либо примера или информации как это можно сделать. Хвостов у виджета в сторону QPaintEngine тоже не обнаружил. :(
Если есть какие либо мысли, с удовольствие выслушаю.

Мысль следующая....
Любой виджет это QPaintDevice, в начале рисования он создает QPainter, которому указывает себя в качестве поверхности для рисования. Этот вызов идет в QPaintEngine::begin( QPaintDevice * pdev ). Это виртуальный метод, если его переопределить, то можно попробовать использовать вместо pdev свое устройство отображения.

Это только мысли.

Автор: rnd 29.9.2009, 17:33

Самое просто в таких случаях - смотреть исходники куте и дебажится

Автор: Litkevich Yuriy 29.9.2009, 17:59

piton, тут меня одна мыслишка посетила. Значится баловался я QWebClient'ом, http://labs.trolltech.com/blogs/2009/09/18/qt-in-the-cloud-with-qwebclient/.
Смысл его простой, вместо корневого виджета в своей программе, например, QWidget, устанавливаешь QWebClient. Компилируешь и запускашь.
Открываешь браузер и вводишь адрес: http://localhost:1818 и видешь в браузере свою программу (и она работает). http://lit-uriy.narod.ru/temp/screen.png

Суть мысли:
я заметил, что работает это так: запускашь свою программу, появляется её окно, но как только ты в браузере обращаешся к ней. Окно обычное исчезает. Стало бвть рисование проболжается не на окошке.

Может там почерпнёшь, чтони-будь интересное?

Автор: BRE 29.9.2009, 19:02

2 piton

Перечитал первый пост темы и у меня возник вопрос, а почему для всего этого не использовать QGraphicsView+QGraphicsScene. Эта связка и обеспечивает необходимый функционал. Глубина элементов есть, виджет на сцену поместить можно.

Автор: piton 30.9.2009, 13:02

Цитата(rnd @ 29.9.2009, 18:33) *
Самое просто в таких случаях - смотреть исходники куте и дебажится

Дебажили, откуда и поняли, что QT рисует на главное окно само.

Цитата(Litkevich Yuriy @ 29.9.2009, 18:59) *
piton, тут меня одна мыслишка посетила. Значится баловался я QWebClient'ом, http://labs.trolltech.com/blogs/2009/09/18/qt-in-the-cloud-with-qwebclient/.
Смысл его простой, вместо корневого виджета в своей программе, например, QWidget, устанавливаешь QWebClient. Компилируешь и запускашь.
Открываешь браузер и вводишь адрес: http://localhost:1818 и видешь в браузере свою программу (и она работает). http://lit-uriy.narod.ru/temp/screen.png

Суть мысли:
я заметил, что работает это так: запускашь свою программу, появляется её окно, но как только ты в браузере обращаешся к ней. Окно обычное исчезает. Стало бвть рисование проболжается не на окошке.

Может там почерпнёшь, чтони-будь интересное?

Сейчас почитаем, потом отпишу о результатах.

Цитата(BRE @ 29.9.2009, 20:02) *
2 piton

Перечитал первый пост темы и у меня возник вопрос, а почему для всего этого не использовать QGraphicsView+QGraphicsScene. Эта связка и обеспечивает необходимый функционал. Глубина элементов есть, виджет на сцену поместить можно.

Для этого надо переделать все, а проект уже идет не первый год. Может в следующих версиях на этом и будем основываться.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)