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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как определить видимую область виджета?  (Прочитано 10662 раз)
Sergeich
Гость
« : Декабрь 14, 2005, 17:53 »

Нужно узнать область виджета, которая находится в пределах экрана и не закрыта другими окнами.
Попробовал юзать QWidget::clipRegion(), он просто возвращает прямоугольник виджета. Если нет решения на Qt, может кно-нить знает как сделать это на WinAPI и X11?
Юзаю Qt 3.3.4 под XP и линухом.
Записан
Agriop
Гость
« Ответ #1 : Декабрь 15, 2005, 10:50 »

А при перерисовке? QPainter::clipRegion() что возвращает?
Записан
Sergeich
Гость
« Ответ #2 : Декабрь 15, 2005, 14:10 »

Цитата: "Agriop"
А при перерисовке? QPainter::clipRegion() что возвращает?

Дык я OpenGL юзаю, из-за этого и проблемы: при рендеринге невидимые пиксели не перерисовываются, вне зависимости от того в  какой буфер рисуешь - передний, задний или дополнительный.
Записан
Dendy
Гость
« Ответ #3 : Декабрь 15, 2005, 18:45 »

А зачем сие нужно? Если делать скриншотьl - то QGLWidget::grabFrameBuffer() - самое оно. Хотя на сколько показьlвает практика - перерисовьlвается всё в фрейм буфере, а вот потеря пикселей может бьlть из-за самой оконной системьl.
Записан
Sergeich
Гость
« Ответ #4 : Декабрь 15, 2005, 19:14 »

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

Сие нужно для двойной буферизации с помощью OpenGL. Технология такая: сначала все рисуется в задний буфер, потом при paintEvent() нужные куски копируются в передний буфер с помощью glCopyPixels(). Практика показывает следующее: если часть QGLWidget закрыта другим окном, пиксели под ней в задний буфер не рисуются, из-за т.н. Pixel Ownership Test.
Записан
fanat9
Гость
« Ответ #5 : Декабрь 15, 2005, 19:59 »

А почему решили делать именно так ? Есть какие-то ограничения ведь судя по описанию проблемы - glwidget не перерисовывается часто.
Записан
Dendy
Гость
« Ответ #6 : Декабрь 15, 2005, 20:53 »

Емммм... Так включить в OpenGL двойную буферизацию (которая кстати включена по умолчанию) и не геммороиться! Если можно - озвучь ключевую задачу, чего собственно вьl пьlтаетесь добиться копированием пикселей, кроме устранения еффекта мерцания?
Записан
Sergeich
Гость
« Ответ #7 : Декабрь 16, 2005, 11:44 »

Задача такая : нужно показывать несколько миллионов 2D объектов с возможностью масштабирования и скроллинга. Для скорости используется OpenGL. Двойная буферизация используется для быстрого скроллинга ( сначала пиксели копируются со смещением, затем подрисовывается только необходимый кусок ) и для рисовки вспомогательных объектов ( например прямоугольника зумирования ) без перерисовки всей картинки. Все это замечательно работает, пока окно не закрыто другими окнами.
Записан
Dendy
Гость
« Ответ #8 : Декабрь 16, 2005, 12:30 »

Попробуй включить двойную буферизацию для QWidget. В Qt4 она включена по умолчанию, в Qt3 - через QPixmap.
Записан
Sergeich
Гость
« Ответ #9 : Декабрь 16, 2005, 17:10 »

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

Хоть убей. Фреймбуфер формируется независимо от поверхности рисования. Всё равно какая часть его скрьlта. Нужно просто сформировать необходимую область и скопировать данньlе фреймбуфера.

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

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

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

Код:
QRegion QWidget::visibleRegion();
Записан
Sergeich
Гость
« Ответ #11 : Декабрь 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
Гость
« Ответ #12 : Декабрь 16, 2005, 18:27 »

Интересно, нужно проверить.

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

Ещё. Когда окно должно перерисоваться оно присьlлает paintEvent() с областью для перерисовки. Внутри собьlтия перерисовьlваешь GL окно, при етом видовую матрицу настраиваешь чтобьl в видимую часть попала необходимая для перерисовки область. Далее копируешь нужньlй кусок, которьlй теперь точно будет виден, так как тебе ето гарантирует paintEvent().
Записан
Sergeich
Гость
« Ответ #13 : Декабрь 16, 2005, 19:06 »

PBuffer можно попробовать, только надо разобраться как быстро скинуть его содержимое в буфер кадра. И что самое хреновое придется выдирать кусок кода из 4.1 и тащить его в 3.3. А перейти на 4-ку я не могу.
 paintEvent() не помогает: например когда посредине окна висит аська в QPaintEvent::region() сидит весь прямоугольник виджета.
Записан
Dendy
Гость
« Ответ #14 : Декабрь 16, 2005, 19:30 »

Цитата: "Sergeich"
paintEvent() не помогает: например когда посредине окна висит аська в QPaintEvent::region() сидит весь прямоугольник виджета.


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


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