Название: QThread && QApplication::postEvent() Отправлено: ZeBriD от Март 13, 2009, 14:31 День добрый.
Столкнулся со следующей проблемой, и никак не могу сообразить, как её решить. Суть проблемы такова: надо обработать большое кол-во файлов (я обрабатываю для теста чуть более 32тыс. таковых). Дабы отменить этот процесс, а также быть в курсе прогресса, решил во время обработки файлов выводить прогрессбар с кнопкой отмены. Первый вариант, который я попробовал - это добавить в функцию обработки файлов QApplication::postEvent(); И оно в принципе работало. Прогресс отображался, при нажатии на кнопку - останавливался. Но! обработка пошла в десятки раз медленнее, что мне совсем не понравилось. Тогда я решил использовать отдельный поток для отображение прогресса. Создал поток, наследник QThread, в котором был один сигнал, на прекращение процесса, и один слот, для увелинчения прогресса на 1. Но и тут всё пошло не чисто. При обработке файлов стабильно сыпятся сообщения "QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread". Да и ко всему прочему, нажать на отмену я так и не могу, пока не вставлю в код потока обработчик событий, который, опять же, замедляет в десятки раз процесс обработки файлов. Собственно, не подскажете, как заставить этот поток работать отдельно от основного, дабы таки была возможность отменить процесс, без добавления QApplication::postEvent() ? Название: Re: QThread && QApplication::postEvent() Отправлено: BRE от Март 13, 2009, 14:36 Попробуй сделать наоборот, т.е. файлы обрабатывай в отдельном потоке, а прогресс-бар рисуй и кнопку обрабатывай в основной потоке.
Название: Re: QThread && QApplication::postEvent() Отправлено: ZeBriD от Март 13, 2009, 17:55 Часть обработки файлов заключается в формировании QTreeWidget, который лежит на главной форме.
Поэтому, перенести обработку файлов в отдельный поток не получится, ибо QTreeWidget будет лежать не в нём, а значит и обрабатываться нормально не сможет... Какие есть ещё варианты ? Название: Re: QThread && QApplication::postEvent() Отправлено: BRE от Март 13, 2009, 18:02 Часть обработки файлов заключается в формировании QTreeWidget, который лежит на главной форме. Вариант тот-же.Поэтому, перенести обработку файлов в отдельный поток не получится, ибо QTreeWidget будет лежать не в нём, а значит и обрабатываться нормально не сможет... Какие есть ещё варианты ? Посылай из потока обработки сигнал addFileName( const QString &filename ), а в главном потоке добавляй в дерево. Имя сигнала и параметры можно менять. Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 13, 2009, 18:33 Столкнулся тут на днях с такой же проблемой. Есть модель со списком файлов, нужно поизвлекать их иконки, что есть очень долго. Сделал так: формирую модель,запускаю поток, передав ему имена файлов, в потоке выбирается иконка и делается emit(int,QIcon), что ловится в моделе на слот и устанавливается в модель. Все под масдаем шло отлично, но под Линем сказало, что с пиксмапом не будет работать не в гуи треде. Что делать ХЗ...
Название: Re: QThread && QApplication::postEvent() Отправлено: spirit от Март 13, 2009, 18:39 юзай QImage. QPixmap нельзя юзать вне главного потока.
из ассистанта, см.Thread Support in Qt Цитировать Painting in Threads ...Painting onto QPixmaps and QWidgets is not supported.... Название: Re: QThread && QApplication::postEvent() Отправлено: ZeBriD от Март 13, 2009, 18:46 Вариант тот-же. Уже думал об этом... Но, после прикидки, понял, что либо получится через чур перенавороченые сигналы с кучей параметров, либо ничего не получится...Посылай из потока обработки сигнал addFileName( const QString &filename ), а в главном потоке добавляй в дерево. Имя сигнала и параметры можно менять. Чтобы было понятнее, у меня обработка файлов тесно связана с QTreeWidget: Код: QTreeWidgetItem *locwi; Возможно глупый вопрос... Но может есть какой-то "локальный" postEvent(), только для одного потока/формы ? Название: Re: QThread && QApplication::postEvent() Отправлено: spirit от Март 13, 2009, 18:47 используй катом ивенты, в них можно запишнуть то, что тебе нужно.
Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 13, 2009, 18:49 юзай QImage. QPixmap нельзя юзать вне главного потока. Да хотелось через QFileIconProvider, чтобы свои костыли не лепить, а там через пиксмап. :(из ассистанта, см.Thread Support in Qt Цитировать Painting in Threads ...Painting onto QPixmaps and QWidgets is not supported.... Название: Re: QThread && QApplication::postEvent() Отправлено: spirit от Март 13, 2009, 18:51 так конвертануть потом QImage в пикспам, что нельзя? :)
Цитировать QPixmap QPixmap::fromImage ( const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor ) [static] Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 13, 2009, 18:53 Да не в том дело. Загляни в исходники QFileIconProvider, там работа через QPixmap, а на выходе QIcon. Т.е. получается, что в потоке оперирую с QPixmap, что не позволено.
Название: Re: QThread && QApplication::postEvent() Отправлено: BRE от Март 13, 2009, 18:54 Чтобы было понятнее, у меня обработка файлов тесно связана с QTreeWidget: [offtop]Вот это очень плохая традиция переплетать функционал и GUI (уж прости ;) ). Представь, что завтра тебе нужно будет сделать тоже, только с использованием не Qt (в консоли!). Будешь заново программу писать? Вместо того, чтобы "морду" новую сделать, а функционал старый оставить. [/offtop] А в сигналах можно любые объекты передовать. Сделай класс FileMegaInfo, создавай объект этого класса, заполни данными и передавай в главный поток, а он на основании этих данных будет дерево заполнять. Название: Re: QThread && QApplication::postEvent() Отправлено: spirit от Март 13, 2009, 18:56 Да не в том дело. Загляни в исходники QFileIconProvider, там работа через QPixmap, а на выходе QIcon. Т.е. получается, что в потоке оперирую с QPixmap, что не позволено. [offtop]типа QFileIconProvider юзается в потоке? че-то не пойму :) [/offtop] Название: Re: QThread && QApplication::postEvent() Отправлено: ZeBriD от Март 13, 2009, 18:58 используй катом ивенты, в них можно запишнуть то, что тебе нужно. Простите, что ? ::)Да, и может кто объяснит, почему таки изначальный вариант, с отображением прогресс-бара в отдельном потоке не работает? [offtop] Тоже верно. Не подумал об этом, ибо это мой первый проект... Спасибо за совет.Вот это очень плохая традиция переплетать функционал и GUI (уж прости ;) ). Представь, что завтра тебе нужно будет сделать тоже, только с использованием не Qt (в консоли!). Будешь заново программу писать? Вместо того, чтобы "морду" новую сделать, а функционал старый оставить. [/offtop] А в сигналах можно любые объекты передовать. Сделай класс FileMegaInfo, создавай объект этого класса, заполни данными и передавай в главный поток, а он на основании этих данных будет дерево заполнять. Похоже, выбор у меня не велик... Попробую так реализовать...Название: Re: QThread && QApplication::postEvent() Отправлено: spirit от Март 13, 2009, 18:59 Да, и может кто объяснит, почему таки изначальный вариант, с отображением прогресс-бара в отдельном потоке не работает? нельзя юзать гуевые классы в негуевом(рабочем) потоке.опять-таки ассистант, см.Thread Support in Qt Код: QObject Reentrancy Название: Re: QThread && QApplication::postEvent() Отправлено: ZeBriD от Март 13, 2009, 19:11 нельзя юзать гуевые классы в негуевом(рабочем) потоке. Спасибо большое за пояснение. опять-таки ассистант, см.Thread Support in Qt Код: QObject Reentrancy Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 13, 2009, 19:11 Да не в том дело. Загляни в исходники QFileIconProvider, там работа через QPixmap, а на выходе QIcon. Т.е. получается, что в потоке оперирую с QPixmap, что не позволено. [offtop]типа QFileIconProvider юзается в потоке? че-то не пойму :) [/offtop] Название: Re: QThread && QApplication::postEvent() Отправлено: spirit от Март 13, 2009, 19:14 Да не в том дело. Загляни в исходники QFileIconProvider, там работа через QPixmap, а на выходе QIcon. Т.е. получается, что в потоке оперирую с QPixmap, что не позволено. [offtop]типа QFileIconProvider юзается в потоке? че-то не пойму :) [/offtop] Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 13, 2009, 19:16 Дык можно что-нибудь сделать без велосипедов?
Название: Re: QThread && QApplication::postEvent() Отправлено: spirit от Март 13, 2009, 19:16 Дык можно что-нибудь сделать без велосипедов? надо подумать. :)а какая задача собственно? Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 13, 2009, 19:19 Ну, типа файловый менеджер пытаюсь писать для саморазвития. ::)
Название: Re: QThread && QApplication::postEvent() Отправлено: spirit от Март 13, 2009, 19:21 так это, а чем QFileSystemModel не подходит для этого дела?
или покриколу самому? :) Название: Re: QThread && QApplication::postEvent() Отправлено: BRE от Март 13, 2009, 19:23 Да, в потоке получаю иконки из QFileIconProvider::icon(QFileInfo&). Залез в исходники, в linux не дает даже сконструировать QPixmap в не GUI-потоке (создает null-pixmap).Наверное от FileIconProvider в отдельном потоке прийдется отказаться. :( Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 13, 2009, 19:24 А как по другому? Неохота самому в винапи пока лезть.
Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 14, 2009, 14:29 так это, а чем QFileSystemModel не подходит для этого дела? Хотя бы потому, что у pagefile.sys не показывает размер и иконку.или покриколу самому? :) Название: Re: QThread && QApplication::postEvent() Отправлено: pastor от Март 14, 2009, 14:38 Хотя бы потому, что у pagefile.sys не показывает размер и иконку. Это давно известный баг в Qt: #167099 - On Windows QFileInfo::exists() returns false for c:\pagefile.sys and c:\hiberfil.sys (http://www.qtsoftware.com/developer/task-tracker/index_html?id=167099&method=entry) Название: Re: QThread && QApplication::postEvent() Отправлено: Пантер от Март 14, 2009, 14:46 Да я знаю, что это баг, уже когда-то на форуме спрашивал. Вот из-за этого сам и решил покопаться. И еще с правами под виндой кака.
|