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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Qt 4.1 + Win Api  (Прочитано 7787 раз)
ElderOrb
Гость
« : Февраль 10, 2006, 16:13 »

Есть библиотека, которая что-то отрисовывает в окно, хэндл на которое в неё передаётся. Есть пример на mfc, в котором всё работает замечательно. В этом примере в обработчиках окна OnMove, OnPaint и OnSize вызываются функции библиотеки OnMove, OnPaint и OnSize. В результате всё красиво работает, всегда обновляется и нету мерцаний.

Но использовать эту библиотеку на мфц мне по понятным причинам совсем не хочется, поэтому я попробовал сделать тоже самое на Qt. Создал я QScrollArea, запихал в неё QWidget и скормил сторонней библиотеке winId() этого виджэта. При этом не забыл установить фильтр событий на этот виджэт и по событиям QEvent::Move, QEvent::Paint и QEvent::Resize происходил вызов библиотечных функций OnMove и т.п. Всё отрисовалось, однако стали наблюдаться следующие странные эффекты:
1. если окошко свернуть/развернуть/открыть/закрыть  то обновление происходит, если же его задвинуть вниз экрана за панель задач а потом поднять - обновления не произойдёт, т.к. QEvent::Paint не придёт.
2. Если потянуть главное окно за правый нижний угол и начать ресайзить то в некоторых случаях картинка нарисованная сторонней библиотекой будет обновляться шустро и без мерцаний, а в некоторых жрать немеряно ресурсов и ужасно мерцать при том.
3. Иногда при ресайзе отрисовки изображения вообще не происходит!.. То есть такое чувство что виджэт заливает всё нарисованное на нём, хотя я сделал setFillAutoBackground(false).

Что с этим всем делать?... Почему в мфц работает а в Qt нет?.. Я чувствую что дело возможно в оконных флагах, но перепробовав несколько из них в разных сочетаниях я понял что это тот самый случай когда тупым перебором ничего не добиться.. Кто-нибудь кто сопрягал Qt с API-шными библиотеками, помогите, пожалуйста,  разобраться!..

Обнаружилось что если использовать QWidget не помещая его в QScrollArea и задать ему атрибут Qt::WA_NoSystemBackground, то вроде всё становится ок. То есть всё дело похоже в QScrollArea.
Записан
Dendy
Гость
« Ответ #1 : Февраль 10, 2006, 17:49 »

MFC - и есть надстройка над WinAPI, так что ничего удивительного, что она склоняется с всякими апишньІми либами. Отдавать кому-либо Qt-шньІй хендл не рекомендуется, так как на собьІтия будут реагировать обе библиотеки и хто знает чё им вздумается вьІтворять с ним. Например, дружно реагировать на изменение размеров.

QWidget должен одинаково нормально работать как сам - так и внутри QScrollArea. Возможно не так обрабатьІваешь координатьІ Move и Resize.

Я нормально спрягал Qt окно с Огром, они дружили. Попробуй ещё отменить бекгроунд окна внутри QScrollArea или поиграться с функцией setUpdatesEnabled();
Записан
ElderOrb
Гость
« Ответ #2 : Февраль 10, 2006, 18:20 »

Цитировать
Отдавать кому-либо Qt-шньІй хендл не рекомендуется, так как на собьІтия будут реагировать обе библиотеки и хто знает чё им вздумается вьІтворять с ним.
Да я и сам понимаю что это не лучший вариант. Я бы попробовал сделать обычное api окно, завернуть его в QWinHost (из Qt Solutions/qtwinmigrate) и уже QWinHost вставить в QScrollArea.. Но.. Нового qtwinmigrate у меня нету а тот что есть (2.0) - компиляется с проблемами и не факт что после моих правок нормально заработает.

Цитировать
QWidget должен одинаково нормально работать как сам - так и внутри QScrollArea. Возможно не так обрабатьІваешь координатьІ Move и Resize.
Отрабатываю их в eventFilter-е предка QScrollArea. Код следующий:

Код:
if(o == w) {
if(e->type() == QEvent::Paint) {
if(paintEnabled) {
View->OnPaint();
qDebug(tr("paint event %1").arg(paint++).toAscii());
}
return false;
} else if(e->type() == QEvent::Move) {
if(paintEnabled) {
View->OnPaint();
qDebug(tr("move event %1").arg(move++).toAscii());
}
return false;
} else if(e->type() == QEvent::Resize) {
if(paintEnabled) {
View->OnPaint();
qDebug(tr("resize event %1").arg(resize++).toAscii());
}
return false;
} else {
return QWidget::eventFilter(o, e);
}

} else {
return QWidget::eventFilter(o, e);
}


Цитировать
Я нормально спрягал Qt окно с Огром, они дружили. Попробуй ещё отменить бекгроунд окна внутри QScrollArea

setAutoFillBackground(false) ? Если да, то делал как для viewport-а, так и для scrollArea.

Цитировать
или поиграться с функцией setUpdatesEnabled();
- а вот это наверное стоит попробовать.. только в каком месте?
Записан
Dendy
Гость
« Ответ #3 : Февраль 11, 2006, 13:37 »

Сходу: фильтр собьІтий в Qt сделан правильно, то-есть QWidget::eventFilter() ровно как и QObject::eventFilter() всегда возвращают false - следовательно вьІзьІвать их не нужно. Вместо ентого следует возвращать true, чтобьІ собьІтие не обработалось самим обьектом.

setUpdatesEnabled( false ) вьІзови для злочастного окна в самом начале при создании - ента функция для юзеров, а не для либьІ. После етого будешь видеть только то, что рисуется сторонними средствами, а не Артуром.
Записан
ElderOrb
Гость
« Ответ #4 : Февраль 11, 2006, 15:24 »

Цитировать
Сходу: фильтр собьІтий в Qt сделан правильно, то-есть QWidget::eventFilter() ровно как и QObject::eventFilter() всегда возвращают false - следовательно вьІзьІвать их не нужно. Вместо ентого следует возвращать true, чтобьІ собьІтие не обработалось самим обьектом.


Не совсем понял, всё-таки правильно или нет? ж)) Почему я возвращаю false - потому что мне и не надо съедать события - в этом случае QFrame, на который выводит библиотека как минимум не отрисует красивую рамочку ж). Впрочем если без этого никак, фиг с нею, с рамочкой..

Цитировать
setUpdatesEnabled( false ) вьІзови для злочастного окна в самом начале при создании - ента функция для юзеров, а не для либьІ. После етого будешь видеть только то, что рисуется сторонними средствами, а не Артуром.


Не вижу причин по которым это не сработает.. Осталось проверить в понедельник ж) Спасибо!
Записан
Dendy
Гость
« Ответ #5 : Февраль 11, 2006, 16:33 »

Я имел в виду, что не стоит писать:

Код:
return QObject::eventFilter( o, e );


или

Код:
return QWidget::eventFilter( o, e );


Под правильной архитектурой подразумевалось, что классьІ ядра Qt используют виртуальньІе функции только для получения гибкости для потомком етих классов. Оригинальная реализация виртуальньІх функций корневьІх классов НЕ делает ничего, если ето специально не оговорено - весь функционал в отдельньІх методах.

Именно поетому большинство классов Qt можно использовать не наследуясь от них.

Но ето так, мелочи стиля (-;
Записан
ElderOrb
Гость
« Ответ #6 : Февраль 14, 2006, 14:42 »

Проблема никуда не исчезла Ж(. В случае с обычным QWidget-ом достаточно сделать на выбор setAttribute(Qt::WA_NoSystemBackground, true); или setUpdatesEnabled(false); После чего мерцание исчезает. Но если этот виджэт я помещаю в QScrollArea - тогда не помогает ничто. Я пробовал для скролаера, вьюпорта и виджэта, setUpdatesEnabled(false); для всех трёх, scrollArea->viewport()->setAutoFillBackground(false); - аналогично.

Да, чуть не забыл. Если по приходу событий QEvent::Paint, QEvent::Move и QEvent::Resize вызывать соответственно библиотечные OnPaint, OnMove и OnResize то мерцание существенно уменьшается. Точнее оно остаётся только в одном случае - если тянуть QScrollArea за уголок.
Записан
Dendy
Гость
« Ответ #7 : Февраль 14, 2006, 18:32 »

В eventFilter() при реагировании на QEvent::Paint возвращай true.
Записан
ElderOrb
Гость
« Ответ #8 : Февраль 14, 2006, 23:26 »

Возвращаю, но похоже этого не достаточно. Очевидно есть ещё какие-то условия при которых Qt стремится обновить виджэт.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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