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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [Qt 4.2] Определение видимой области виджета  (Прочитано 8688 раз)
Muller
Гость
« : Март 22, 2007, 20:06 »

Здравствуйте!
Есть ли какой-либо способ в Qt определить видимую область виджета, когда он частично перекрыт другими окнами? Пробовал использовать функцию QWidget::visibleRegion(), но она всегда возвращает результат, аналогичный QWidget::rect().
Задача состоит в следующем: есть приложение, состоящее из большого числа окон, открытых одновременно, которые периодически перерисовываются по мере поступления данных. Надо обновлять только видимые на экране виджеты, иначе загрузка процессора растет пропорционально числу открытых окон. Функцию update() вызываю сам, поэтому перерисовывается абсолютно все виджеты, даже скрытые. Способа определить, виден ли виджет на экране (частично или полностью), пока не нашел.
Записан
Sergeich
Гость
« Ответ #1 : Март 22, 2007, 20:38 »

В Qt такого способа нет. Средствами WinAPI или X11 это достать можно, но проблематично Грустный
Записан
Tonal
Гость
« Ответ #2 : Март 24, 2007, 14:02 »

А окна учитывают видимый регион при отрисовки?
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #3 : Март 25, 2007, 23:47 »

так это... PaintEvent же не генерится для виджетов, которые не видимы. update() будет перекрашивать тока видимые окна...
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
_govorilka
Гость
« Ответ #4 : Март 26, 2007, 06:39 »

Приложение состоящее из большего числа окон не есть гуд. Чем меньше окон, тем меньше проблем!!! Можеть большая половина из них вообще не нужна?.. Может все данные можно отображать в одном окне?.. То что, отрисовка сильно загружает процессор - уменьши частоту обновления (при отображении данных 1-2 раз в секунду более чем достаточно).
Записан
Muller
Гость
« Ответ #5 : Март 26, 2007, 12:43 »

Цитата: "Racheengel"
так это... PaintEvent же не генерится для виджетов, которые не видимы. update() будет перекрашивать тока видимые окна...

Я тоже сначал так думал. Оказалось не так... PaintEvent действительно не посылается невидимым виджетам, но только тем, для которых isVisble()==false. Если виджет скрыт под другим окном, то он невидимым не считается.
Цитата: "_govorilka"
Приложение состоящее из большего числа окон не есть гуд. Чем меньше окон, тем меньше проблем!!! Можеть большая половина из них вообще не нужна?.. Может все данные можно отображать в одном окне?.. То что, отрисовка сильно загружает процессор - уменьши частоту обновления (при отображении данных 1-2 раз в секунду более чем достаточно).

К сожалению, таковы требования заказчика. Хотят видеть несколько окон, и все тут. Период обновления и так 1 сек, увеличить нельзя.
Пока что вижу единственно приемлемое решение - ограничить число открытых окон, скажем, 5-ю. Больше вряд ли кто будет смотреть одновременно. Но более красивым решением было бы определение видимой части виджета.
Записан
Alex03
Гость
« Ответ #6 : Март 26, 2007, 14:02 »

А это не катит?
Цитировать

QRegion QWidget::clipRegion () const
Returns the unobscured region where paint events can occur.

For visible widgets, this is an approximation of the area not covered by other widgets; otherwise, this is an empty region.

The repaint() function calls this function if necessary, so in general you do not need to call it.

По идее оно само и должно быть, но видимо относится не к топлевел окнам, за них уже ОС/Иксы думают.
Записан
Muller
Гость
« Ответ #7 : Март 26, 2007, 15:02 »

В Qt 4.2 функции QRegion QWidget::clipRegion() нет, но, судя по описанию, она заменена функцией QWidget::visibleRegion(), о которой я писал в первом посте.
Записан
Tonal
Гость
« Ответ #8 : Март 26, 2007, 20:17 »

Похоже таки ошибочка в Qt

Код:

QRegion QWidget::visibleRegion() const
{
    return d_func()->clipRect();
}

И хотя есть QRegion QWidgetPrivate::clipRegion() const
Она нигде не вызывается...
Записан
Muller
Гость
« Ответ #9 : Март 27, 2007, 15:21 »

Нашел способ, как определить, перекрыт виджет другим окном или нет, средствами X11. Как определить видимую область, пока не нашел, но мне вполне будет достаточно и этого.
Может кому интересно будет.
Для начала разрешим виджету обрабатывать событие VisibilityNotify, так как оно по умолчанию не обрабатывается.
Код:

#ifdef Q_WS_X11
XSelectInput(QX11Info::display(), winId(),
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
KeymapStateMask |
ButtonMotionMask | PointerMotionMask |
EnterWindowMask | LeaveWindowMask |
FocusChangeMask |
ExposureMask |
PropertyChangeMask |
StructureNotifyMask |
VisibilityChangeMask);
#endif

Затем определим функцию x11Event:
Код:

#ifdef Q_WS_X11
bool QMyWidget::x11Event(XEvent *event)
{
if (event->type == VisibilityNotify)
m_state = event->xvisibility.state;

return QWidget::x11Event(event);
}
#endif

Переменная m_state хранит состояние окна. Она может принимать значения VisibilityUnobscured (виджет виден полностью), VisibilityPartiallyObscured (частично перекрыт) и VisibilityFullyObscured (полностью перекрыт). При обновлении данных анализируем значение m_state и принимаем решение, перерисовывать окно или нет.
Спасибо всем участвовавшим в обсуждении.
Записан
Alex03
Гость
« Ответ #10 : Март 28, 2007, 08:53 »

А что и как Вы рисуете?
ДУмаю, что если разбить всё окно на несколько зон, и рисовать их поотдельности то Винда/Иксы будут очень быстро "выполнять рисование" в полностью невидимых областях.
Ну и в раинтЭвенте конечно надо рисовать только ту область, которая передаётся с эвэнтом.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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