Russian Qt Forum

Qt => Общие вопросы => Тема начата: Muller от Март 22, 2007, 20:06



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


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Sergeich от Март 22, 2007, 20:38
В Qt такого способа нет. Средствами WinAPI или X11 это достать можно, но проблематично :(


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Tonal от Март 24, 2007, 14:02
А окна учитывают видимый регион при отрисовки?


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Racheengel от Март 25, 2007, 23:47
так это... PaintEvent же не генерится для виджетов, которые не видимы. update() будет перекрашивать тока видимые окна...


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: _govorilka от Март 26, 2007, 06:39
Приложение состоящее из большего числа окон не есть гуд. Чем меньше окон, тем меньше проблем!!! Можеть большая половина из них вообще не нужна?.. Может все данные можно отображать в одном окне?.. То что, отрисовка сильно загружает процессор - уменьши частоту обновления (при отображении данных 1-2 раз в секунду более чем достаточно).


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Muller от Март 26, 2007, 12:43
Цитата: "Racheengel"
так это... PaintEvent же не генерится для виджетов, которые не видимы. update() будет перекрашивать тока видимые окна...

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

К сожалению, таковы требования заказчика. Хотят видеть несколько окон, и все тут. Период обновления и так 1 сек, увеличить нельзя.
Пока что вижу единственно приемлемое решение - ограничить число открытых окон, скажем, 5-ю. Больше вряд ли кто будет смотреть одновременно. Но более красивым решением было бы определение видимой части виджета.


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Alex03 от Март 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.

По идее оно само и должно быть, но видимо относится не к топлевел окнам, за них уже ОС/Иксы думают.


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Muller от Март 26, 2007, 15:02
В Qt 4.2 функции QRegion QWidget::clipRegion() нет, но, судя по описанию, она заменена функцией QWidget::visibleRegion(), о которой я писал в первом посте.


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Tonal от Март 26, 2007, 20:17
Похоже таки ошибочка в Qt

Код:

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

И хотя есть QRegion QWidgetPrivate::clipRegion() const
Она нигде не вызывается...


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Muller от Март 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 и принимаем решение, перерисовывать окно или нет.
Спасибо всем участвовавшим в обсуждении.


Название: [Qt 4.2] Определение видимой области виджета
Отправлено: Alex03 от Март 28, 2007, 08:53
А что и как Вы рисуете?
ДУмаю, что если разбить всё окно на несколько зон, и рисовать их поотдельности то Винда/Иксы будут очень быстро "выполнять рисование" в полностью невидимых областях.
Ну и в раинтЭвенте конечно надо рисовать только ту область, которая передаётся с эвэнтом.