Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите разобаться с потоками.
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
franza
Я начинающий в Qt. Разбираюсь с многопоточностью и не могу написать код, который одновременно менял значение QLCDNumber и постоянно нажимает кнопочку. Прошу помочь разобраться.

lcdthread.h

#ifndef LCDTHREAD_H
#define LCDTHREAD_H

#include <QThread>

class LCDThread : public QThread
{
    Q_OBJECT
private:
    int m_nValue;
public:
    LCDThread(QObject *parent = 0);
    void run();
signals:
    void currentValue(int);
};

#endif // LCDTHREAD_H


pbthread.h
#ifndef PBTHREAD_H
#define PBTHREAD_H

#include <QThread>

class PBThread : public QThread
{
    Q_OBJECT
public:
    PBThread(QObject *parent = 0);
    void run();
signals:
    void finished();
    void click();
public slots:
    void slotClick();
};

#endif // PBTHREAD_H


lcdthread.cpp
#include "lcdthread.h"
#include <QTimer>
LCDThread::LCDThread(QObject *parent) :
    QThread(parent),
    m_nValue(0)
{
}
void LCDThread::run()
{
    while (true) {
        emit currentValue(++m_nValue);
    }
    exec();
}


pbthread.cpp
#include "pbthread.h"

PBThread::PBThread(QObject *parent) :
    QThread(parent)
{
}
void PBThread::run()
{
    while(true) {
        emit click();
    }

    exec();
}

void PBThread::slotClick()
{
    emit click();
}


main.cpp
#include <QtGui>
#include "lcdthread.h"
#include "pbthread.h"
int main(int argc, char** argv)
{
    QApplication a(argc, argv);

    QLCDNumber *plcd = new QLCDNumber(8);
    LCDThread lcdThread;
    plcd->setSegmentStyle(QLCDNumber::Flat);

    QObject::connect(&lcdThread, SIGNAL(currentValue(int)), plcd, SLOT(display(int)));

    QPushButton *ppbutton = new QPushButton("PUSH, FUCKING PSUH");
    PBThread pbThread;

    QObject::connect(&pbThread, SIGNAL(click()), ppbutton, SLOT(animateClick()));

    QWidget wgt;
    QHBoxLayout *l = new QHBoxLayout;
    l->addWidget(plcd);
    l->addWidget(ppbutton);
    wgt.setLayout(l);

    lcdThread.start();
    pbThread.start();
    wgt.show();
    return a.exec();
}


Не могу сделать так, чтобы родительский виджет был доступен для перетаскиваний и прочего. Или для него надо писать свой поток?
Litkevich Yuriy
виджеты могут находится только в главном потоке. Но ими можно управлять через сигналы и слоты из других потоков.

П.С.
Цитата(franza @ 9.1.2011, 23:02) *
не могу написать код, который одновременно менял значение QLCDNumber
с начала разберись с этим, потом будешь усложнять задачу.
franza
виджеты создаются в главном потоке (по крайней мере в main.cpp), в run для каждого потока я написал только отправку сигналов, к которым в main.cpp коннектится соответствующий слот. здесь, думаю, я не ошибся. но при выполнении родительский виджет повисает и не дает себя ни перетаскивать ни закрывать, хотя по идее находится в отдельном потоке.
Litkevich Yuriy
Цитата(franza @ 10.1.2011, 0:41) *
о при выполнении родительский виджет повисает и не дает себя ни перетаскивать ни закрывать, хотя по идее находится в отдельном потоке.
Цитата(Litkevich Yuriy @ 10.1.2011, 0:02) *
виджеты могут находится только в главном потоке.
ufna
Чет мне подсказывает, что закидывать в while() сообщениями без пауз - это не лучший метод :) виджеты живут в основном потоке, но если они получают неприрывный поток сигналов, они это отрабатывают и не дают возможности сигналам и событиям перемещения прийти.
franza
ufna, то есть, в принципе, написано все правильно, только надо usleep(100500) написать?
ufna
Вообще по-хорошему не так делается :) Можно сделать класс "посылатель сигналов" и пихать его в поток, при этом не переопределяя поток, а делая moveToThread - это будет более правильно.

А здесь я не уверен насчет сигналов до exec() в потоке.
franza
ufna, можно поподробней?

Litkevich Yuriy, я имею ввиду, что этот отдельный поток, где создаются виджеты и есть главный.
Litkevich Yuriy
franza, ту по-русски вообще понимаешь?
franza
Litkevich Yuriy, понимаю. Можешь попробовать рассказать о моей ошибке не в одном предложении, а подробнее, так как видно, что я мало понимаю. Мне непонятно следующее: 3 виджета (лсд, кнопка, и базовый, куда они помещаются) создаются в main.cpp. При этом они создаются в главном потоке или нет? Если нет, то как создать их в главном потоке? Слоты, к которым происходит коннект вызываются в главном потоке или нет?
Litkevich Yuriy
Цитата(franza @ 10.1.2011, 18:47) *
я имею ввиду, что этот отдельный поток, где создаются виджеты и есть главный.
лучше главный поток и называть главным, чтобы никого столку не сбивать.
Цитата(franza @ 10.1.2011, 20:28) *
3 виджета (лсд, кнопка, и базовый, куда они помещаются) создаются в main.cpp. При этом они создаются в главном потоке или нет?
Да. Всё что не является наследником QThread и не использует moveToThread() находится в главном потоке.

Цитата(Litkevich Yuriy @ 10.1.2011, 20:45) *
Всё что не является наследником QThread
если быть более точным, то - сам наследник QThread создаётся в главном потоке, а затем вызывается его метод start(), который, в свою очередь, вызывает метод run(). Дак вот именно метод run() и выполняется в отдельном потоке, и как следствие, все объекты созданные в методе run() находятся в отдельном потоке.



Цитата(franza @ 10.1.2011, 20:28) *
Слоты, к которым происходит коннект вызываются в главном потоке или нет?
Слоты находятся в том потоке, в котором находится их объект. Если у тебя все виджеты в главном потоке, то и их слоты соответственно тоже в главном потоке, но это справедливо для соединений типа "авто" (по умолчанию) и "в очередь"(queued).



Цитата(ufna @ 10.1.2011, 4:15) *
А здесь я не уверен насчет сигналов до exec() в потоке.
Собственноручно посылать сигнал можно, а вот, например, сигнал от таймера (созданного здесь же) уже посылаться не будет, т.к. локальная очередь событий не запущена и в таймере не произойдёт события "таймаут"

Ну а вообще:
Цитата(ufna @ 10.1.2011, 1:59) *
... виджеты живут в основном потоке, но если они получают неприрывный поток сигналов, они это отрабатывают и не дают возможности сигналам и событиям перемещения прийти.
+100
franza
спасибо, вроде разобрался. напишу еще, если появятся вопросы.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.