QThread i watki

0

Probuje podpiac do watku odswiezanie w glownym oknie aplikacji pewnych danych, jednak widac nie bardzo rozumiem dzialanie bo za nic mi to nie wychodzi. Tak wiec prosze o pomoc.

QThreadEx - pomocnicza klasa tworze watek i przenosze QObject ktory emituje sygnal do mainwindow przez moveToThread

#ifndef QTHREADEX_H
#define QTHREADEX_H

#include <QThread>

class QThreadEx : public QThread
{
protected:
    void run() { exec(); }
};

#endif // QTHREADEX_H

klasa color

#ifndef COLOR_H
#define COLOR_H

#define _WIN32_WINNT 0x0403
#include <windows.h>
#include <QObject>
#include "kalwindow.h"

struct COLOR
{
    DWORD red;
    DWORD green;
    DWORD blue;
};

class Color : public QObject
{
    Q_OBJECT
private:
...
public:
    Color();
    ~Color();
    COLOR Update();
    void run();
signals:
    void signal(COLOR color);
};

#endif // COLOR_H

//color.cpp

void Color::run()
{
    int i = 0;
    while(1)
    {
        _sleep(200);
        i++;
        if(i==1000)
            emit signal(Update());
    }
}

funkcja Update() zwraca mi strukture COLOR na podstawie polozenia myszki. Sygnal powinien emitowac COLOR.

mainwindow

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private:
    Ui::MainWindow *ui;
    KalWindow *Kal;
    Color *cKal;
    QThreadEx cKalThread;

private slots:
    void CStart();
    void CStop();
    void Update(COLOR color);
};

// mainwindow.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    Kal = new KalWindow();

    if(Kal->Get_isSet())
    {        
        cKal = new Color();
        cKal->moveToThread(&cKalThread);
        cKal->connect(cKal,SIGNAL(signal(COLOR)),this,SLOT(Update(COLOR)));

        connect(ui->Start,SIGNAL(clicked()),this,SLOT(CStart()));
        connect(ui->Stop,SIGNAL(clicked()),this,SLOT(CStop()));
    }
}

void MainWindow::Update(COLOR color)
{
    QString text;
    text.setNum(color.blue);
    ui->blue->setText(text);
    text.setNum(color.green);
    ui->green->setText(text);
    text.setNum(color.red);
    ui->red->setText(text);
}

void MainWindow::CStart()
{
    cKalThread.start();
}

void MainWindow::CStop()
{
    cKalThread.terminate();
}

Nie wiem czy dobrze to rozumiem ale tworze QObject cKal potem pakuje go do watku cKalThread i kiedy uruchomie go przyciskiem start powinien wyemitowac sygnal update co chwile a potem funkcja Update powinna mi uaktualnic labele. Jednak tak nie jest ;).

Jesli jakis glupi blad zrobilem to przepraszam ale chory jestem, tak czytam o tych watkach i juz nic nie wiem ;).

0
Krycho napisał(a)

Nie wiem czy dobrze to rozumiem ale tworze QObject cKal potem pakuje go do watku cKalThread i kiedy uruchomie go przyciskiem start powinien wyemitowac sygnal update co chwile a potem funkcja Update powinna mi uaktualnic labele. Jednak tak nie jest ;).

Jesli jakis glupi blad zrobilem to przepraszam ale chory jestem, tak czytam o tych watkach i juz nic nie wiem ;).

Ano błąd jest i to poważny. Klasa Color powinna dziedziczyć po QThread, trzeba wtedy ten wątek wystartować i porobić connecty między klasami, natomiast nie wiem po co w ogóle jest QThreadEx...

0

Ano robilem to na ten wzor. Nizej mozna sciagnac gotowy kod. Tworzy producenta i konsumenta dziedziczacych po QObject. Oni obydwoje emituja pewne sygnaly miedzy soba. Dalej tworzy on watki i przenosi do tych watkow producenta i konsumenta. Laczy sloty i odpala. I dziala. Wydaje mi sie ze ten pan wiedzial co robi i jak powinno sie to robic. Widac ja nie bardzo potrafie to odwzorowac u siebie.

http://labs.qt.nokia.com/2006/12/04/threading-without-the-headache/

1

Po kiego grzyba ci wątek? czemu nie zastosujesz timer-a?
Nie mówiąc już o tym, że dokładnie nic, wykonuje się w twoim wątku!
Jeśli jednak się upierasz na ten wątek, to:
#nie potrzebujesz klasy QThreadEx (ktoś powinien cię zastrzelić za tą nazwę, ten prefix jest zarezerwowany dla biblioteki Qt)
#QObject-ów NIGDY nie przekazuje się przez wartość (dziwne, że ci się to skompilowało).
#w klasie Color (znowu nazwa do d..py, ale z innego powodu) brakuje slotu wykonywanego w wątku.
Może chodzi ci o coś takiego:

class ZmieniaczKolorow : public QObject
{
    Q_OBJECT
private:
...
public:
    ZmieniaczKolorow();
    ~ZmieniaczKolorow();

public slots:
    void zmieniajKolory();
signals:
    void nowyKolor(const QColor &color);
};

void ZmieniaczKolorow::zmieniajKolory() {
    for (int i=0; i<24; i++) {
        _sleep(200);
        if (i%3==0)
            emit nowyKolor(Qt::red);

        if (i%3==1)
            emit nowyKolor(Qt::green);

        if (i%3==2)
            emit nowyKolor(Qt::white);
    }
}


        cKal = new ZmieniaczKolorow();
        cKal->moveToThread(&cKalThread);
        cKal->connect(cKal,SIGNAL(nowyKolor(QColor)),
                  this, SLOT(Update(QColor)));
 
        connect(ui->Start,SIGNAL(clicked()),
                   cKal, SLOT(zmieniajKolory()));

Moim zdaniem wtaczasz wielką armatę by ustrzelić muchę z własnego nosa.

0

Robilem to na podstawie tego kodu ze strony qt

#include <QtCore>
#include <stdio.h>

enum {
    Limit = 123456,
    BlockSize = 7890
};

class Producer : public QObject
{
    Q_OBJECT
    QByteArray data;
    int bytes;

public:
    inline Producer() : bytes(0) { }

public slots:
    void produce()
    {
        int remaining = Limit - bytes;
        if (remaining == 0) {
            emit finished();
            return;
        }

        // this will never happen
        if (data.size() != 0)
            qFatal("Producer: Consumer failed to consume!");

        int size = qMin(int(BlockSize), remaining);
        bytes += size;
        remaining -= size;
        data.fill('Q', size);

        printf("Producer: produced %d more bytes, %d of %d total\n", size, bytes, Limit);
        emit produced(&data);
    }

signals:
    void produced(QByteArray *data);
    void finished();
};

class Consumer : public QObject
{
    Q_OBJECT
    int bytes;

public:
    inline Consumer() : bytes(0) { }

public slots:
    void consume(QByteArray *data)
    {
        // this will never happen
        if (data->size() == 0)
            qFatal("Consumer: Producer failed to produce!");

        int remaining = Limit - bytes;
        int size = data->size();
        remaining -= size;
        bytes += size;
        data->clear();

        printf("Consumer: consumed %d more bytes, %d of %d total\n", size, bytes, Limit);
        emit consumed();
        if (remaining == 0)
            emit finished();
    }

signals:
    void consumed();
    void finished();
};

class QThreadEx : public QThread
{
protected:
    void run() { exec(); }
};

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);

    // create the producer and consumer and plug them together
    Producer producer;
    Consumer consumer;
    producer.connect(&consumer,
                     SIGNAL(consumed()),
                     SLOT(produce()));
    consumer.connect(&producer,
                     SIGNAL(produced(QByteArray *)),
                     SLOT(consume(QByteArray *)));

    // they both get their own thread
    QThreadEx producerThread;
    producer.moveToThread(&producerThread);
    QThreadEx consumerThread;
    consumer.moveToThread(&consumerThread);

    // start producing once the producer's thread has started
    producer.connect(&producerThread,
                     SIGNAL(started()),
                     SLOT(produce()));

    // when the consumer is done, it stops its thread
    consumerThread.connect(&consumer,
                           SIGNAL(finished()),
                           SLOT(quit()));
    // when consumerThread is done, it stops the producerThread
    producerThread.connect(&consumerThread,
                           SIGNAL(finished()),
                           SLOT(quit()));
    // when producerThread is done, it quits the application
    app.connect(&producerThread,
                SIGNAL(finished()),
                SLOT(quit()));

    // go!
    producerThread.start();
    consumerThread.start();

    return app.exec();
}

#include "main.moc"

Nie jestem pewien gdzie przekazalem przez wartosc QObject. Moglbys rozjasnic? Chcialem uzyc watkow bo nie mialem innego pomyslu na to jak zrobic wyswietlanie w czasie rzeczywistym bez blokowania calego okna programu w czasie kiedy to dziala. Jesli jest jakis prostszy sposob to oczywiscie chetnie poslucham.

To ze trzeba zrobic public slot juz sam dojrzalem w tym kodzie z ktorego sie wzoruje. Jednak to nic nie zmienilo nadal po wystartowaniu watku nie emituje on sygnalu. Tak jakby funkcja emitujaca sygnal nie byla wcale wywolywana.

EDIT

Ok dzieki za klase QTimer duzo prostsza niz watki. Wywalilem te wszystkie watkie i dziedziczenie po QObject dodalem sobie timer i co 100ms pobiera i odswieza mi dane. ;)

Ps. Moze znacie jakies biblioteki do pomocy z obsluga plikow .ini? np. mam login=... pass=... zeby wyciagac dane po okreslonych znacznikach.

1

Znamy.Zowie się toto QSettings.

0

Widac qt ma w sobie wszystko ;) Bardzo fajna i prosta rzecz. Wszystko ladnie dziala, dzieki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1