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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Многопоточный вывод на QGraphicsScene  (Прочитано 12266 раз)
BiTOk
Гость
« : Май 03, 2010, 08:32 »

Доброе время суток. Пишу эмулятор прохождения по тоннелю людей. Каждый человек должен быть реализован в виде потока. Создаю несколько потоков, в них пытаюсь отрисовать человечков на QGraphicsScene, но они не рисуются и в консоль получаю вывод:
QObject::startTimer: timers cannot be started from another thread
QObject::killTimer: timers cannot be stopped from another thread
Как лучше реализовать такое, чтобы не было столь большого разделяемого ресурса и было хоть сколько-то плавное движение? Кто выводит в консоль эти сообщения?
Записан
alexman
Гость
« Ответ #1 : Май 03, 2010, 13:01 »

Рисовка возможна только в главном потоке! Например, посылай сигналы из потоков в главный поток, что требуется отрисоваться!
Записан
BiTOk
Гость
« Ответ #2 : Май 03, 2010, 13:04 »

Т.е. фактически Вы мне предлагаете реализовать очередь, куда будут кидаться запросы на различные действия, а в главном потоке эту очередь обрабатывать и отрисовывать? В каком виде реализовать это лучше: руками реализовать очередь и по таймеру её обрабатывать или какой другой механизм?
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #3 : Май 03, 2010, 13:15 »

обрабатывать по мере поступления сигналов из доппотоков
Записан

Юра.
BiTOk
Гость
« Ответ #4 : Май 03, 2010, 13:17 »

А как правильно реализовать саму очередь?
Записан
ilyagoo
Гость
« Ответ #5 : Май 03, 2010, 13:21 »

соединяй сигнал-слот с флагом Qt::QueuedConnection
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Май 03, 2010, 14:29 »

Т.е. фактически Вы мне предлагаете реализовать очередь, куда будут ..
Эта очередь давно имеется - eventLoop главной нитки. Все что Вам надо это из дочерних ниток посылать сигналы в главную, а там их обрабатывать/отрисовывать
Записан
BiTOk
Гость
« Ответ #7 : Май 05, 2010, 07:53 »

Сделал как Вы и сказали, сигналы отправляю главному треду. Реализовал так:
Код:
Worker::Worker(int startPlace, QObject *parent):QThread()//позиция, откуда следует начинать путь
{
    x = 25.5; //абсцисса всегда такая, ибо это сразу после начальной стены
    y = startPlace*25+25.5;

    this->parent = parent;
    myPeople = NULL;
}

void Worker::run()
{
    emit makeWorker(this, x, y);
    moveTimer = new QTimer( this );
    connect( moveTimer, SIGNAL(timeout()), this, SLOT(onTimerDown()) );
    moveTimer->start( 50 );
    qDebug("%d", this->currentThreadId());
    exec();
}

void Worker::onTimerDown()
{
    qDebug("%d onTimerDown", this->currentThreadId());
    emit moveWorker(this, myPeople);
}
Но таймер работает не в контексте нового потока, а из главного. Как правильно запустить таймер из этого потока, чтобы он срабатывал в нём же?
Записан
BRE
Гость
« Ответ #8 : Май 05, 2010, 08:02 »

Попробуй так:
Код
C++ (Qt)
void Worker::run()
{
   emit makeWorker(this, x, y);
   QTimer moveTimer;
   connect( &moveTimer, SIGNAL(timeout()), this, SLOT(onTimerDown()) );
   moveTimer.start( 50 );
   qDebug("%d", this->currentThreadId());
   exec();
}
 
Записан
BiTOk
Гость
« Ответ #9 : Май 05, 2010, 08:07 »

Попробуй так:
5840 bla
3064
5840 onTimerDown
Что означает, что таймер вновь срабатывает в контексте главного потока
Записан
alexman
Гость
« Ответ #10 : Май 05, 2010, 08:08 »

Можно попробовать sleep делать в run! То есть отказаться от таймера!
Записан
BRE
Гость
« Ответ #11 : Май 05, 2010, 08:12 »

Вместо this->currentThreadId(), попробуй писать QThread::currentThreadId()
Записан
BiTOk
Гость
« Ответ #12 : Май 05, 2010, 08:17 »

alexman
Пробовал, даёт достаточно скверный результат, ибо слип не совсем эквивалент таймеру, он даст остановку после выполнения (а выполнение может быть не быстрым), а не как таймер..
BRE
Это не принципиально, ибо данные результаты верны.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #13 : Май 05, 2010, 08:24 »

среди меня бытует мнение, что соединясь со слотом у объекта, созданного в главной нитке (Worker) мы таки будем выполнять этот слот в главной нитке, что вам в общем-то и надо. Создайте еще 1 объект внутри run и к неиу уже вешайте коннекты.
могу ошибаться, тк с QThread работал очень давно
Записан
BiTOk
Гость
« Ответ #14 : Май 05, 2010, 08:25 »

среди меня бытует мнение, что соединясь со слотом у объекта, созданного в главной нитке (Worker) мы таки будем выполнять этот слот в главной нитке, что вам в общем-то и надо.
могу ошибаться. тк с QThread работал очень давно
Цитировать
Qt::BlockingQueuedConnection - при генерации сигнал помещается в очередь обработки событий. Пока слот не получит сигнал текущий поток блокируется. Данный тип соединения следует применять только для получателя в другом потоке
Вообще это не так судя по всему.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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