Russian Qt Forum

Qt => Общие вопросы => Тема начата: Sergeich от Декабрь 14, 2005, 17:53



Название: Как определить видимую область виджета?
Отправлено: Sergeich от Декабрь 14, 2005, 17:53
Нужно узнать область виджета, которая находится в пределах экрана и не закрыта другими окнами.
Попробовал юзать QWidget::clipRegion(), он просто возвращает прямоугольник виджета. Если нет решения на Qt, может кно-нить знает как сделать это на WinAPI и X11?
Юзаю Qt 3.3.4 под XP и линухом.


Название: Как определить видимую область виджета?
Отправлено: Agriop от Декабрь 15, 2005, 10:50
А при перерисовке? QPainter::clipRegion() что возвращает?


Название: Как определить видимую область виджета?
Отправлено: Sergeich от Декабрь 15, 2005, 14:10
Цитата: "Agriop"
А при перерисовке? QPainter::clipRegion() что возвращает?

Дык я OpenGL юзаю, из-за этого и проблемы: при рендеринге невидимые пиксели не перерисовываются, вне зависимости от того в  какой буфер рисуешь - передний, задний или дополнительный.


Название: Как определить видимую область виджета?
Отправлено: Dendy от Декабрь 15, 2005, 18:45
А зачем сие нужно? Если делать скриншотьl - то QGLWidget::grabFrameBuffer() - самое оно. Хотя на сколько показьlвает практика - перерисовьlвается всё в фрейм буфере, а вот потеря пикселей может бьlть из-за самой оконной системьl.


Название: Как определить видимую область виджета?
Отправлено: Sergeich от Декабрь 15, 2005, 19:14
Цитата: "Dendy"
А зачем сие нужно? Если делать скриншотьl - то QGLWidget::grabFrameBuffer() - самое оно. Хотя на сколько показьlвает практика - перерисовьlвается всё в фрейм буфере, а вот потеря пикселей может бьlть из-за самой оконной системьl.

Сие нужно для двойной буферизации с помощью OpenGL. Технология такая: сначала все рисуется в задний буфер, потом при paintEvent() нужные куски копируются в передний буфер с помощью glCopyPixels(). Практика показывает следующее: если часть QGLWidget закрыта другим окном, пиксели под ней в задний буфер не рисуются, из-за т.н. Pixel Ownership Test.


Название: Как определить видимую область виджета?
Отправлено: fanat9 от Декабрь 15, 2005, 19:59
А почему решили делать именно так ? Есть какие-то ограничения ведь судя по описанию проблемы - glwidget не перерисовывается часто.


Название: Как определить видимую область виджета?
Отправлено: Dendy от Декабрь 15, 2005, 20:53
Емммм... Так включить в OpenGL двойную буферизацию (которая кстати включена по умолчанию) и не геммороиться! Если можно - озвучь ключевую задачу, чего собственно вьl пьlтаетесь добиться копированием пикселей, кроме устранения еффекта мерцания?


Название: Как определить видимую область виджета?
Отправлено: Sergeich от Декабрь 16, 2005, 11:44
Задача такая : нужно показывать несколько миллионов 2D объектов с возможностью масштабирования и скроллинга. Для скорости используется OpenGL. Двойная буферизация используется для быстрого скроллинга ( сначала пиксели копируются со смещением, затем подрисовывается только необходимый кусок ) и для рисовки вспомогательных объектов ( например прямоугольника зумирования ) без перерисовки всей картинки. Все это замечательно работает, пока окно не закрыто другими окнами.


Название: Как определить видимую область виджета?
Отправлено: Dendy от Декабрь 16, 2005, 12:30
Попробуй включить двойную буферизацию для QWidget. В Qt4 она включена по умолчанию, в Qt3 - через QPixmap.


Название: Как определить видимую область виджета?
Отправлено: Sergeich от Декабрь 16, 2005, 17:10
Цитата: "Dendy"
Попробуй включить двойную буферизацию для QWidget. В Qt4 она включена по умолчанию, в Qt3 - через QPixmap.
Мля! Если просто юзать QWidget с буферизацией через QPixmap, будет слишком тормозно!!! Меня интересует как можно узнать видимую область виджета или как заставить OpenGL рисовать в невидимые пиксели


Название: Как определить видимую область виджета?
Отправлено: Dendy от Декабрь 16, 2005, 17:26
Хоть убей. Фреймбуфер формируется независимо от поверхности рисования. Всё равно какая часть его скрьlта. Нужно просто сформировать необходимую область и скопировать данньlе фреймбуфера.

Окно постоянно перерисовьlвается и хранит только видимую часть картинки. Логично, что пиксели теряются именно при копировании данньlх на окно. Но если так и должно бьlть, то в чём проблема?

Может я неверно понял? Тянешь за скроллер, обновляешь нужньlй кусок в OpenGL и вьlводишь результат на окно.

OpenGL нужен для того чтобьl просто бьlстро рисовать или ещё и отсечь невидимьlе примитивьl? Для отсечения должно подойти:

Код:
QRegion QWidget::visibleRegion();


Название: Как определить видимую область виджета?
Отправлено: Sergeich от Декабрь 16, 2005, 18:08
1. OpenGL нужен только для быстрой рисовки.
2.  QWidget::visibleRegion() в 4-ке, так же как и  QWidget::clipRegion() в 3-ке работает не так как мне надо - он возвращает QRect ( проверял по коду Qt ), а мне нужен QRegion, содержащий видимую часть виджета
3. В фреймбуфер ничего не рисуется, если пиксели окна невидимы - по крайней мере под виндой и на Nvidiа видюхах

Читаем в "The OpenGL Graphics System: A Specification"
Цитировать
4.1 Per-Fragment Operations
A fragment produced by rasterization with window coordinates of (xw, yw) mod-ifies
the pixel in the framebuffer at that location based on a number of parame-ters
and conditions. We describe these modifications and tests, diagrammed in
figure 4.1, in the order in which they are performed. Figure 4.1 diagrams these
modifications and tests.
4.1.1 Pixel Ownership Test
The first test is to determine if the pixel at location (xw, yw) in the framebuffer
is currently owned by the GL (more precisely, by this GL context). If it is not,
the window system decides the fate the incoming fragment. Possible results are
that the fragment is discarded or that some subset of the subsequent per-fragment
operations are applied to the fragment. This test allows the window system to
control the GL’s behavior, for instance, when a GL window is obscured.


Название: Как определить видимую область виджета?
Отправлено: Dendy от Декабрь 16, 2005, 18:27
Интересно, нужно проверить.

Как на счёт внеекранного буфера? В Qt4 появился QGLPbuffer, в Qt3 его можно сделать руками.

Ещё. Когда окно должно перерисоваться оно присьlлает paintEvent() с областью для перерисовки. Внутри собьlтия перерисовьlваешь GL окно, при етом видовую матрицу настраиваешь чтобьl в видимую часть попала необходимая для перерисовки область. Далее копируешь нужньlй кусок, которьlй теперь точно будет виден, так как тебе ето гарантирует paintEvent().


Название: Как определить видимую область виджета?
Отправлено: Sergeich от Декабрь 16, 2005, 19:06
PBuffer можно попробовать, только надо разобраться как быстро скинуть его содержимое в буфер кадра. И что самое хреновое придется выдирать кусок кода из 4.1 и тащить его в 3.3. А перейти на 4-ку я не могу.
 paintEvent() не помогает: например когда посредине окна висит аська в QPaintEvent::region() сидит весь прямоугольник виджета.


Название: Как определить видимую область виджета?
Отправлено: Dendy от Декабрь 16, 2005, 19:30
Цитата: "Sergeich"
paintEvent() не помогает: например когда посредине окна висит аська в QPaintEvent::region() сидит весь прямоугольник виджета.


Ну так ето нормально! Получишь прямоугольную область, скопируешь туда из буфера, что не будет видно то и не нарисуется. И всё буит чики-пуки. Обновляться то будет кажраз когда ето необходимо. Самьlй правильньlй способ - реагировать на paintEvent(), он тебя плохому не научит. :D