Russian Qt Forum
Июля 06, 2025, 13:52 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QThread && QApplication::postEvent()  (Прочитано 16310 раз)
ZeBriD
Гость
« : Марта 13, 2009, 14:31 »

День добрый.
Столкнулся со следующей проблемой, и никак не могу сообразить, как её решить.
Суть проблемы такова: надо обработать большое кол-во файлов (я обрабатываю для теста чуть более 32тыс. таковых).
Дабы отменить этот процесс, а также быть в курсе прогресса, решил во время обработки файлов выводить прогрессбар с кнопкой отмены.
Первый вариант, который я попробовал - это добавить в функцию обработки файлов QApplication::postEvent();
И оно в принципе работало. Прогресс отображался, при нажатии на кнопку - останавливался.
Но! обработка пошла в десятки раз медленнее, что мне совсем не понравилось.
Тогда я решил использовать отдельный поток для отображение прогресса.
Создал поток, наследник QThread, в котором был один сигнал, на прекращение процесса, и один слот, для увелинчения прогресса на 1.
Но и тут всё пошло не чисто.
При обработке файлов стабильно сыпятся сообщения "QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread".
Да и ко всему прочему, нажать на отмену я так и не могу, пока не вставлю в код потока обработчик событий, который, опять же, замедляет в десятки раз процесс обработки файлов.

Собственно, не подскажете, как заставить этот поток работать отдельно от основного, дабы таки была возможность отменить процесс, без добавления QApplication::postEvent() ?
Записан
BRE
Гость
« Ответ #1 : Марта 13, 2009, 14:36 »

Попробуй сделать наоборот, т.е. файлы обрабатывай в отдельном потоке, а прогресс-бар рисуй и кнопку обрабатывай в основной потоке.
Записан
ZeBriD
Гость
« Ответ #2 : Марта 13, 2009, 17:55 »

Часть обработки файлов заключается в формировании QTreeWidget, который лежит на главной форме.
Поэтому, перенести обработку файлов в отдельный поток не получится, ибо QTreeWidget будет лежать не в нём, а значит и обрабатываться нормально не сможет...
Какие есть ещё варианты ?
Записан
BRE
Гость
« Ответ #3 : Марта 13, 2009, 18:02 »

Часть обработки файлов заключается в формировании QTreeWidget, который лежит на главной форме.
Поэтому, перенести обработку файлов в отдельный поток не получится, ибо QTreeWidget будет лежать не в нём, а значит и обрабатываться нормально не сможет...
Какие есть ещё варианты ?
Вариант тот-же.
Посылай из потока обработки сигнал addFileName( const QString &filename ), а в главном потоке добавляй в дерево.
Имя сигнала и параметры можно менять.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5877


Жаждущий знаний


Просмотр профиля WWW
« Ответ #4 : Марта 13, 2009, 18:33 »

Столкнулся тут на днях с такой же проблемой. Есть модель со списком файлов, нужно поизвлекать их иконки, что есть очень долго. Сделал так: формирую модель,запускаю поток, передав ему имена файлов, в потоке выбирается иконка и делается emit(int,QIcon), что ловится в моделе на слот и устанавливается в модель. Все под масдаем шло отлично, но под Линем сказало, что с пиксмапом не будет работать не в гуи треде. Что делать ХЗ...
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
spirit
Гость
« Ответ #5 : Марта 13, 2009, 18:39 »

юзай QImage. QPixmap нельзя юзать вне главного потока.
из ассистанта, см.Thread Support in Qt
Цитировать
Painting in Threads
...Painting onto QPixmaps and QWidgets is not supported....
Записан
ZeBriD
Гость
« Ответ #6 : Марта 13, 2009, 18:46 »

Вариант тот-же.
Посылай из потока обработки сигнал addFileName( const QString &filename ), а в главном потоке добавляй в дерево.
Имя сигнала и параметры можно менять.
Уже думал об этом... Но, после прикидки, понял, что либо получится через чур перенавороченые сигналы с кучей параметров, либо ничего не получится...
Чтобы было понятнее, у меня обработка файлов тесно связана с QTreeWidget:
Код:
  QTreeWidgetItem *locwi;
  bool same[] = {false, true, true, true, true, true, true, true};
  for (int i = 0; i < filModel->rowCount(*mi); i++)
  {
    if ((filModel->fileInfo(mi->child(i,0)).isDir()) && (filModel->rowCount(mi->child(i,0)) > 0))
    {
      locwi = new QTreeWidgetItem(wi);
      locwi->setText( 0, filModel->fileName(mi->child( i, 0 )));
      locwi->setIcon( 0, filModel->fileIcon(mi->child( i, 0 )));
      locwi->setText( 8, filModel->filePath(mi->child( i, 0 )));
      locwi->setText( 9, "Folder");
      LookUp(&mi->child(i, 0), locwi);
     
    }
   
    if (filModel->fileInfo( mi->child( i, 0 )).isFile())
    {
      TagLib::FileRef fl(filModel->filePath( mi->child( i, 0) ).toAscii().data());

      locwi = new QTreeWidgetItem(wi);
      locwi->setText( 0, filModel->fileName( mi->child( i, 0) ));
      locwi->setIcon( 0, filModel->fileIcon( mi->child( i, 0) ));
      locwi->setText( 8, filModel->filePath( mi->child( i, 0) ));
      locwi->setText( 9, "File");
      locwi->setText( 1, QString::fromStdWString(fl.tag()->artist().toWString()));
      locwi->setText( 2, QString::fromStdWString(fl.tag()->title().toWString()));
      locwi->setText( 3, QString::fromStdWString(fl.tag()->album().toWString()));
      locwi->setText( 4, QString::number(fl.tag()->year()));
      locwi->setText( 5, QString::number(fl.tag()->track()));
      locwi->setText( 6, QString::fromStdWString(fl.tag()->genre().toWString()));
      locwi->setText( 7, QString::fromStdWString(fl.tag()->comment().toWString()));
     
      emit incProgVal();
     
    }
   
    for (int j = 1; j <= 8; j++)
      if ( (same[j]) && (i > 0) )
        if (wi->child(i - 1) != NULL)
          if (locwi->text(j) != wi->child(i - 1)->text(j))
            same[j] = false;
   
    if (cancel)
    {
      return;
    }
    //QApplication::processEvents();
  }
 
  for (int j = 1; j <= 8 ; j++)
    if (same[j])
      if (wi->child(0) != NULL)
        wi->setText(j, wi->child(0)->text(j));

Возможно глупый вопрос... Но может есть какой-то "локальный" postEvent(), только для одного потока/формы ?
Записан
spirit
Гость
« Ответ #7 : Марта 13, 2009, 18:47 »

используй катом ивенты, в них можно запишнуть то, что тебе нужно.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5877


Жаждущий знаний


Просмотр профиля WWW
« Ответ #8 : Марта 13, 2009, 18:49 »

юзай QImage. QPixmap нельзя юзать вне главного потока.
из ассистанта, см.Thread Support in Qt
Цитировать
Painting in Threads
...Painting onto QPixmaps and QWidgets is not supported....
Да хотелось через QFileIconProvider, чтобы свои костыли не лепить, а там через пиксмап. Грустный
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
spirit
Гость
« Ответ #9 : Марта 13, 2009, 18:51 »

так конвертануть потом QImage в пикспам, что нельзя?  Улыбающийся
Цитировать
QPixmap QPixmap::fromImage ( const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor )   [static]
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5877


Жаждущий знаний


Просмотр профиля WWW
« Ответ #10 : Марта 13, 2009, 18:53 »

Да не в том дело. Загляни в исходники QFileIconProvider, там работа через QPixmap, а на выходе QIcon. Т.е. получается, что в потоке оперирую с QPixmap, что не позволено.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
BRE
Гость
« Ответ #11 : Марта 13, 2009, 18:54 »

Чтобы было понятнее, у меня обработка файлов тесно связана с QTreeWidget:
[offtop]
Вот это очень плохая традиция переплетать функционал и GUI (уж прости  Подмигивающий ). Представь, что завтра тебе нужно будет сделать тоже, только с использованием не Qt (в консоли!). Будешь заново программу писать? Вместо того, чтобы "морду" новую сделать, а функционал старый оставить.
[/offtop]
А в сигналах можно любые объекты передовать. Сделай класс FileMegaInfo, создавай объект этого класса, заполни данными и передавай в главный поток, а он на основании этих данных будет дерево заполнять.
Записан
spirit
Гость
« Ответ #12 : Марта 13, 2009, 18:56 »

Да не в том дело. Загляни в исходники QFileIconProvider, там работа через QPixmap, а на выходе QIcon. Т.е. получается, что в потоке оперирую с QPixmap, что не позволено.
[offtop]
типа QFileIconProvider юзается в потоке? че-то не пойму Улыбающийся
[/offtop]
Записан
ZeBriD
Гость
« Ответ #13 : Марта 13, 2009, 18:58 »

используй катом ивенты, в них можно запишнуть то, что тебе нужно.
Простите, что ?  Строит глазки


Да, и может кто объяснит, почему таки изначальный вариант, с отображением прогресс-бара в отдельном потоке не работает?


[offtop]
Вот это очень плохая традиция переплетать функционал и GUI (уж прости  Подмигивающий ). Представь, что завтра тебе нужно будет сделать тоже, только с использованием не Qt (в консоли!). Будешь заново программу писать? Вместо того, чтобы "морду" новую сделать, а функционал старый оставить.
[/offtop]
Тоже верно. Не подумал об этом, ибо это мой первый проект... Спасибо за совет.

А в сигналах можно любые объекты передовать. Сделай класс FileMegaInfo, создавай объект этого класса, заполни данными и передавай в главный поток, а он на основании этих данных будет дерево заполнять.
Похоже, выбор у меня не велик... Попробую так реализовать...
Записан
spirit
Гость
« Ответ #14 : Марта 13, 2009, 18:59 »

Да, и может кто объяснит, почему таки изначальный вариант, с отображением прогресс-бара в отдельном потоке не работает?
нельзя юзать гуевые классы в негуевом(рабочем) потоке.
опять-таки ассистант, см.Thread Support in Qt
Код:
QObject Reentrancy
...Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant.
They can only be used from the main thread. As noted earlier,
QCoreApplication::exec() must also be called from that thread...
« Последнее редактирование: Марта 13, 2009, 19:02 от spirit » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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