Russian Qt Forum
Ноябрь 22, 2024, 11:56
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Разное
>
Говорилка
>
Тестовое задание на программиста С++/Qt компания некстерс
Страниц:
1
2
3
[
4
]
5
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Тестовое задание на программиста С++/Qt компания некстерс (Прочитано 49286 раз)
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #45 :
Сентябрь 05, 2016, 11:45 »
Цитата: ssoft от Сентябрь 05, 2016, 10:56
В том то и дело, что подготовку данных для финального отображения (где учитывается и порядок, и много чего еще - эффекты, текстуры и т.п.) можно совершенно параллельно, да и обрабатывать события GUI и др. можно независимо от финальной процедуры отображения.
И формально только реализованная в Qt стратегия обработки событий накладывает ограничения на принадлежность всего дерева Widget одному и тому же потоку.
Думаю "собственно рисованием" занимается обработчик события UpdateRequest. Это он вызывает paintEvent рекурсивно. Начиная с пятерки рисуется все в QImage (хотя это противоречит double-buffer). В конце обработчик вызывает нативный API для вывода на экран.
ОС посылает событие рисования (что выливается в UpdateRequest) в той нитке где создано QApplication (обычно главной). Просто вызвать UpdateRequest из др нитки может и можно (не проверял), но эффекта не имеет т.к. нет dirtyRegions - нужен сначала update, а он вызовет рисование в главной.
Записан
GreatSnake
Джедай : наставник для всех
Offline
Сообщений: 2921
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #46 :
Сентябрь 05, 2016, 12:40 »
Помимо рисования есть ещё так называемый "focus-manager", который занимается рассылкой клавиатурных событий непосредственно виджетам.
Если кто не знает, то все клавиатурные события от системы приходят в top-level окно и уже непосредственно тулкит занимается их управлением.
Так вот всё это управление тоже далается в обработчике событий gui-потока.
Записан
Qt 5.11/4.8.7 (X11/Win)
ssoft
Программист
Offline
Сообщений: 584
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #47 :
Сентябрь 05, 2016, 13:20 »
Цитата: Old от Сентябрь 05, 2016, 11:02
Да ничего она не накладывает. Можно рисовать хоть все виджеты сцены, каждый в своем потоке, правда рисовать придется в буфер (QImage). А вот окончательное рисование придется выполнять в paintEvent. Вот как раз метод paintEvent и вызывает тот самый, кто-знает порядок отрасивки всех виджетов и без кторого нормально сцену не построить.
Это только один из возможных методов), нативно реализованный в Qt. Но внутри paintEvent можно только готовить данные для отрисовки кадра (менять атрибуты графических узлов сцены, готовить QImage, или вообще напрямую заполнять массивы в видеопамяти), а непосредственно отображением может заниматься отдельная сущность в отдельном потоке, совершенно никак не связанная ни с QWidget, ни с Qt. Порядок отрисовки зависит только от порядка графических узлов сцены, а частота кадров может никак и не зависеть от частоты вызовов paintEvent.
Вопрос был другой - Почему GUI в Qt всегда однопоточный. Сам процесс отображения не накладывает никаких ограничений на многопоточность GUI, а вот обеспечение правильного порядка обработки событий клавиатуры или мыши можно легко достигнуть с помощью ограничения однопоточности, да и за голыми указателями не нужно следить, и signal/slot в виде Direct соединений, и множество других небрежных плюшек. Изначально GUI было спроектировано таким образом, а далее ...
Цитировать
А так как менять эту систему - значит переписать очень много много кода и ещё больше сил потратить на поддержку устаревших программ, то это никому не надо. Так и живём
Это ограничение так сильно пронизывает Qt, что устранять его не целесообразно. Проще написать другой инструментарий.
Записан
Racheengel
Джедай : наставник для всех
Offline
Сообщений: 2679
Я работал с дискетам 5.25 :(
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #48 :
Сентябрь 05, 2016, 14:19 »
Я другого не понимаю - а зачем вам всем так многопоточный гуй сдался?
Разве что для второго монитора?
Рисовать в буфер и сейчас можно и в потоках, а потом в главном гуе собирать картинку.
Какие будут преимущества иметь много гуепотоков
Записан
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 не волк, в лес не уйдёт
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #49 :
Сентябрь 05, 2016, 14:24 »
Цитата: ssoft от Сентябрь 05, 2016, 13:20
а непосредственно отображением может заниматься отдельная сущность в отдельном потоке
Ну Тролли и поместили эту сущность в первую (главную) нитку процесса, а могли бы это же делать и в отдельной нитке. Именно эта сущность вызывает paintEvent, а готовить данные для отображения можно в других 100500 нитках.
Цитата: ssoft от Сентябрь 05, 2016, 13:20
совершенно никак не связанная ни с QWidget, ни с Qt.
И что получиться: венда/XWindow/...?
Большим достоинством Qt является то, что она может самостоятельно все отрисовать внутри некой области/top-level окна.
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #50 :
Сентябрь 05, 2016, 14:26 »
Цитата: Racheengel от Сентябрь 05, 2016, 14:19
Я другого не понимаю - а зачем вам всем так многопоточный гуй сдался?
Я бы вообще с удовольствием послушал четкую формулировку "многопоточного гуя".
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #51 :
Сентябрь 05, 2016, 14:37 »
Цитата: Racheengel от Сентябрь 05, 2016, 14:19
Я другого не понимаю - а зачем вам всем так многопоточный гуй сдался?
Да, применение ограничено, но есть. Не всегда удается вынести трудоемкую операцию в поток чтобы оставить UI свободным. В этом случае хорошо бы рисовать индикатор из "не UI" нитки. В этом году обсуждали.
Записан
ssoft
Программист
Offline
Сообщений: 584
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #52 :
Сентябрь 05, 2016, 15:30 »
Цитата: Old от Сентябрь 05, 2016, 14:24
Ну Тролли и поместили эту сущность в первую (главную) нитку процесса, а могли бы это же делать и в отдельной нитке. Именно эта сущность вызывает paintEvent, а готовить данные для отображения можно в других 100500 нитках.
Не могли Троли вызывать paintEvent "и в отдельной нитке"
, так как это привело бы к необходимости синхронизации внутренностей QWidget и производных классов. В этом и отличие отдельной независимой сущности отображения и сущности вызывающей paintEvent.
Цитировать
Я бы вообще с удовольствием послушал четкую формулировку "многопоточного гуя".
Здесь как раз все просто). GUI является частным случаем отображением чего-либо. Отображение может складываться из данных разной природы - разные источники данных, разные виды отображаемой информации и т.д. Иногда, целесообразно для данных разной природы иметь независимые друг от друга сущности, управляющие их отображением и реагирующие на события изменения данных (подгрузка, пересчет, уточнение деталлизации данных) или GUI события. Когда отображаемых элементов боольшое количество, а требуемое время отклика достаточно мало, многопоточность становится весьма актуальной.
Записан
ssoft
Программист
Offline
Сообщений: 584
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #53 :
Сентябрь 05, 2016, 15:53 »
Такой пример. Предположим необходимо отобразить два независимых GUI для управления устройством 1 и устройством 2 в одном. Существует также требование, что изменение состояние устройств должно быть отображено не позднее, чем 100 мс. При выполнении операции после нажатия на кнопку устройства 1 происходит подготовка данных порядка нескольких секунд. Что делать в однопоточной реализации GUI?
Естественное решение - формировать дополнительный поток (с соответствующими накладными расходами), обеспечивающий подготовку данных, или как-то использовать processEvents(). В многопоточном GUI в этом нет необходимости, так как отображение и реакция на события уже многопоточны (асинхронны).
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #54 :
Сентябрь 05, 2016, 16:08 »
Цитата: ssoft от Сентябрь 05, 2016, 15:30
Не могли Троли вызывать paintEvent "и в отдельной нитке"
, так как это привело бы к необходимости синхронизации внутренностей QWidget и производных классов.
Могли. Нужно было синхронизировать только доступ к теневому буферу виджета.
Цитата: ssoft от Сентябрь 05, 2016, 15:30
В этом и отличие отдельной независимой сущности отображения и сущности вызывающей paintEvent.
Нет никаких отличий. paintEvent это синоним получения теневого буфера окна. Он необходим для любого варианта отображения.
Цитата: ssoft от Сентябрь 05, 2016, 15:30
Здесь как раз все просто). GUI является частным случаем отображением чего-либо. Отображение может складываться из данных разной природы - разные источники данных, разные виды отображаемой информации и т.д. Иногда, целесообразно для данных разной природы иметь независимые друг от друга сущности, управляющие их отображением и реагирующие на события изменения данных (подгрузка, пересчет, уточнение деталлизации данных) или GUI события. Когда отображаемых элементов боольшое количество, а требуемое время отклика достаточно мало, многопоточность становится весьма актуальной.
Можно готовить теневые буферы хоть в 100500 потоках, конечное отображение
всегда
будет однопоточным. Не могут окна конкурировать друг с другом, каша будет получаться.
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #55 :
Сентябрь 05, 2016, 16:14 »
Цитата: ssoft от Сентябрь 05, 2016, 15:53
Естественное решение - формировать дополнительный поток (с соответствующими накладными расходами), обеспечивающий подготовку данных, или как-то использовать processEvents(). В многопоточном GUI в этом нет необходимости, так как отображение и реакция на события уже многопоточны (асинхронны).
Окна устройства 1 и устройства 2 могут перекрываться, как они будут обновляться на экране?
Окно устройства 1 обновляется 1 раз в 100 мс, окно устройства 2 обновляется 1 раз в 5 сек. Окно устройства 2 перекрывает на половину окно устройства 1. Как будет обновляться видимая часть окна устройства 1? Кто будет это контролировать?
Записан
ssoft
Программист
Offline
Сообщений: 584
Re: Тестовое задание на программиста С++/Qt комп
«
Ответ #56 :
Сентябрь 05, 2016, 16:54 »
Цитата: Old от Сентябрь 05, 2016, 16:14
Окна устройства 1 и устройства 2 могут перекрываться, как они будут обновляться на экране?
Окно устройства 1 обновляется 1 раз в 100 мс, окно устройства 2 обновляется 1 раз в 5 сек. Окно устройства 2 перекрывает на половину окно устройства 1. Как будет обновляться видимая часть окна устройства 1? Кто будет это контролировать?
Да, вполне могут и перекрываться). Кадр или его часть, формируется отдельной сущностью (Renderer), которая оперирует графом графических примитивов. GUI устройств асинхронно оперируют с узлами данного графа, добавляя/изменяя/удаляя их. Renderer в соответствии с этим графом может обновлять кадр по таймеру, или по изменению графа или еще как-то, асинхронно относительно GUI. Порядок рисования кадра определяется графом примитивов, а не каждым GUI устройств отдельно. При этом подготовка кадра Renderer'ом может быть многопроходной и многопоточной (конкурентной) при необходимости.
Асинхронный (многопоточный) GUI не означает независимую друг от друга и конкурирующую отрисовку, а означает независимую обработку событий и управление отображаемыми примитивами. Когда операции одного GUI не блокируют любой другой.
«
Последнее редактирование: Сентябрь 05, 2016, 17:06 от ssoft
»
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Тестовое задание на программиста С++/Qt комп
«
Ответ #57 :
Сентябрь 05, 2016, 17:14 »
Цитата: ssoft от Сентябрь 05, 2016, 16:54
Кадр или его часть, формируется отдельной сущностью (Renderer)
Так вот этот самый рендерер и есть та самая сущность, которая однопоточно все отрисовывает. Про нее я вам и речь веду.
Если вы все отрисовки виджетов будете делать в других потоках на QImage, а в paintEvent просто рисовать полученный QImage на виджет, у вас получиться тот самый способ отрисовки, в котором Qt будет в роли рендерера.
Записан
ssoft
Программист
Offline
Сообщений: 584
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #58 :
Сентябрь 05, 2016, 17:43 »
Цитата: Old от Сентябрь 05, 2016, 17:14
Так вот этот самый рендерер и есть та самая сущность, которая однопоточно все отрисовывает. Про нее я вам и речь веду.
Так это я давно понял
. Просто многопоточный GUI (о чем собственно разговор) и способ отображения - разные вещи. Многопоточный GUI подразумевает независимую реакцию элементов GUI на события, без явных взаимных блокировок друг друга и рендерера. А уж каким способом происходит формирование кадра (граф, набор QImage или др.) это уже дело конкретной реализации рендерера. При этом рендерер сам по себе может быть и многопоточный, те же QImage можно совмещать и параллельно для разных ветвей иерархии.
PS: Да, и нарямую вызывать метод paintEvent чревато, так как GUI элемент может быть и удален ненароком в момент вызова, отображаем то асинхронно. Лучше уж QImage держать независимо от GUI в отдельном дереве рендерера.
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Тестовое задание на программиста С++/Qt компания некстерс
«
Ответ #59 :
Сентябрь 05, 2016, 20:04 »
Цитата: ssoft от Сентябрь 05, 2016, 17:43
При этом рендерер сам по себе может быть и многопоточный, те же QImage можно совмещать и параллельно для разных ветвей иерархии.
Нет. Если элементы ветвей могут перекрываться - не может. А именно про это идет речь. Qt изначально умел рисовать все сам в frame buffer (что являлось его огромным плюсом), поэтому он сам является тем оконным композитором, который должен все отобразить. А это, для перекрывающихся виджетов, можно сделать только в один поток.
Цитата: ssoft от Сентябрь 05, 2016, 17:43
PS: Да, и нарямую вызывать метод paintEvent чревато, так как GUI элемент может быть и удален ненароком в момент вызова, отображаем то асинхронно. Лучше уж QImage держать независимо от GUI в отдельном дереве рендерера.
Когда вызывается paintEvent уже никто удалиться не может, потому что он может вызывается только из того самого рендерера, который должен быть в конечном итоге однопоточным. И именно он хранит иерархию отображаемых объектов.
Цитата: ssoft от Сентябрь 05, 2016, 17:43
Многопоточный GUI подразумевает независимую реакцию элементов GUI на события, без явных взаимных блокировок друг друга и рендерера.
Ok, с отображением вопросы отпали, остались с реакцией.
А что в Qt принципиально не позволяет сделать независимую реакцию элементов?
«
Последнее редактирование: Сентябрь 05, 2016, 21:46 от Old
»
Записан
Страниц:
1
2
3
[
4
]
5
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...