QThread Kommunikation

vrcat

Mitglied
Hallo zusammen seit langem sitze ich mal wieder mit Qt an. Mein Problem ist recht leicht erklärt ich habe eine GUI Anwendung mit dem QT Creator geschrieben. Dabei habe ich ein QLabel auf meinem Fenster dieses besitzt nach Doku einen Public Slot setPixmap. Nun möchte ich gernen aus einem Thread herraus diesen Slot aufrufen. Der Thread selbst wurde von meinem Hauptprogramm erstellt. Eine einfache connect Anweisung will er bei mir leider nicht durchgehen lassen könnt ihr mir vielleicht helfen.
Schonmal vielen DANK an alle ...
 
Hallo vrcat,

versuchs mal mit
connect(&sender, SIGNAL(signal(parameter)), &dein_label, SLOT(setPixmap(parameter)), Qt::QueuedConnection);

Das sollte dein Problem beheben. Bei Signal und Slot verbindungen zwischen 2 threads musst du vorsichtig sein. Am besten liest du dir die Dokumentation zu QThreads durch und auch zu Qt::ConnectionType.

Gruß, random.
 
Hallo random-access,
vielen Danke für deine Antwort. Leider behebt es nicht mein Problem
muss ich mein GUI in einem seperaten Thread laufen lasse? Wenn
/a wie kann ich das machen.

Gruß vrcat
 
Hallo vrcat,

nein, du musst die GUI nicht in einem anderen Thread laufen lassen.

Kannst du mal den Code deines Threads zeigen? Also die Instanziierung deines Threads, Konstruktor, run und connect sollten reichen ;)
 
Also habe heute noch so einiges ausprobiert aber er will nicht!

Hier also der Header meines Threads:
Code:
#ifndef UEYECAMERA_H
#define UEYECAMERA_H

#include "uEye.h"
#include <QThread>
#include <QLabel>

class UEyeCamera : public QThread {

    Q_OBJECT

private:
    // Kamerainformationen ------------------------------------------
    UEYE_CAMERA_INFO  m_hCamInf;
    HIDS              m_hCam;
    int               m_nWidth;
    int               m_nHeight;
    // Bildspeicher im RAM des Rechners -----------------------------
    QVector<int>      m_nFrameIDs;
    QVector<char*>    m_hFrames;
    // UI-Element der GUI -------------------------------------------
    QLabel           *m_hView;

    // Thread-Status ------------------------------------------------
    bool             m_bFinished;

public:
    // Konstruktor & Dekonstruktor ----------------------------------
    UEyeCamera(UEYE_CAMERA_INFO hCamera);
    ~UEyeCamera();
    // Thread-Funktionen zum Starten und anhalten -------------------
    void    start();
    void    run();
    void    finished();
    // UI-Elemente --------------------------------------------------
    void    connectLabel(QLabel *label);
    void    disconnectLabel();
    void    updateLabel();

signals:
    void    pixmapReady(QPixmap pixmap);

};

#endif // UEYECAMERA_H

nun die cpp
Code:
/*! *****************************************************************
 * Initialisieren der Kamera-Klasse
 *******************************************************************/
UEyeCamera::UEyeCamera(UEYE_CAMERA_INFO hCamera) {
    // Initialisieren -----------------------------------------------
    m_hCamInf           = hCamera;
    m_hCam              = m_hCamInf.dwCameraID;
    m_hView             = NULL;
}

/*! *****************************************************************
 * Verbindung zur Kamera löschen und den Speicher wieder frei geben.
 *******************************************************************/
UEyeCamera::~UEyeCamera() {
    // Abmelden der Kamera und freigeben des Speichers --------------
    is_ExitCamera(m_hCam);
    // Entfernen aller mit der Kamera verknüpften Bildspeicher ------
    int nRet = is_ClearSequence(m_hCam);
    if (nRet != IS_SUCCESS) return;
    for (int i=0;i<m_hFrames.size();i++) delete m_hFrames.at(i);
    // Verbundenes Label lösen --------------------------------------
    disconnectLabel();
}

/*! *****************************************************************
 * Startet den Thread und verbindet die Kamera-Events
 *******************************************************************/
void UEyeCamera::start() {
    // Verbinden der Kamera und Konfigurieren -----------------------
    int  nRet = is_InitCamera (&m_hCam, NULL);
    if (nRet != IS_SUCCESS) {
        // Prüfen ob die Firmware der Kamera mit dem Treiber
        // Kompatibel ist.
        if (nRet == IS_STARTER_FW_UPLOAD_NEEDED) return;
//TODO:! Firmware upload der Kamera
        return;
    }
    // Bild im Systemspeicher (RAM) erfassen ------------------------
    nRet = is_SetDisplayMode(m_hCam,IS_SET_DM_DIB);
    // Default Konfiguration der Kamera vornehmen -------------------
    int  xpos = 0,ypos = 0,width = 640,height = 480;
    m_nWidth  = 640;
    m_nHeight = 480;
    // Setzen des Bildausschnittes der Kamera -----------------------
    nRet = is_SetAOI(m_hCam, IS_SET_IMAGE_AOI,
                     &xpos, &ypos, &width, &height);
    if (nRet != IS_SUCCESS) return;
    // Setzen des 8-Bit RGB Farbmodus -------------------------------
    nRet = is_SetColorMode(m_hCam, IS_CM_RGB8_PACKED);
    if (nRet != IS_SUCCESS) return;
    // Pixeltakt ----------------------------------------------------
    is_SetPixelClock(m_hCam,25);
    //is_SetFrameRate(m_hCam,20,&fps);
    // Triggermodus einschalten, High-Active Blitzmodus setzen ------
    is_SetExternalTrigger(m_hCam, IS_SET_TRIGGER_SOFTWARE);
    //is_SetFlashStrobe(m_hCam, IS_SET_FLASH_HI_ACTIVE);
    // Automatischen Weißabgleich aktivieren ------------------------
    double dblAutoWb = 1.0;
    is_SetAutoParameter(m_hCam,IS_SET_AUTO_WB_ONCE,
                        &dblAutoWb, NULL);
    dblAutoWb = 1.0;
    is_SetAutoParameter(m_hCam,IS_SET_ENABLE_AUTO_WHITEBALANCE,
                        &dblAutoWb, NULL);
    // Thread zur erkennung des Weißabgleichendes starten -----------
/*  if (m_oneShotWBListener == NULL) {
        m_oneShotWBListener=new UEyeEventThread(getDeviceId(),m_hCam);
        m_oneShotWBListener->start(IS_SET_EVENT_WB_FINISHED);
    }*/

    // Entfernen aller mit der Kamera verknüpften Bildspeicher ------
    nRet = is_ClearSequence (m_hCam);
    // Allokieren und Verbinden des zwei Bildspeichers --------------
    for (int nFrames = 0;nFrames<2;nFrames++) {
        char *img = NULL;
        int   nID = -1;
        nRet = is_AllocImageMem(m_hCam,width,height,24, &img, &nID);
        if (nRet == IS_SUCCESS) {
            nRet = is_AddToSequence(m_hCam, img, nID);
            if (nRet != IS_SUCCESS) return;
        } else return;
        m_nFrameIDs.append(nID);
        m_hFrames.append(img);
    }
    // Aktivieren des 1. Bidlspeichers zur Bildaufnahme -------------
    nRet = is_SetImageMem (m_hCam,m_hFrames.at(0),m_nFrameIDs.at(0));
    if (nRet != IS_SUCCESS) return;
    // NewFrame Event Konfigurieren und Threadstarten ---------------
    nRet = is_EnableEvent(m_hCam,IS_SET_EVENT_FRAME);
    // Event detection der Kamera starten
    if (nRet == 0) {
        m_bFinished = false;
        QThread::start();
    }
    // Starten der Frame abfrage ------------------------------------
    is_FreezeVideo(m_hCam, IS_WAIT);

}

/*! *****************************************************************
 * Warten auf Kamera-Events zum Berechnen des Volumens der Kamera
 * und der kamera Position und Orientierung
 *******************************************************************/
void UEyeCamera::run() {
    // Auf das Kameraevent "Neues Bild" warten und Shillouetten------
    // berechnen sowie das Kamera Volumen
    while(!m_bFinished) {
        if (is_WaitEvent(m_hCam,IS_SET_EVENT_FRAME,1)==IS_SUCCESS) {

            updateLabel();

        }
    }
    // Thread wurder abgebrochen und Event wird gelöst
    is_DisableEvent(m_hCam, IS_SET_EVENT_FRAME);
    is_ExitEvent(m_hCam, IS_SET_EVENT_FRAME);
}

/*! *****************************************************************
 * Setzt den Status des Kamera-Threads auf beenden
 *******************************************************************/
void UEyeCamera::finished() {
    m_bFinished = true;
}


/*! *****************************************************************
 * Verbindet das Kamerabild mit einem UI-Element (Label)
 *******************************************************************/
void UEyeCamera::connectLabel(QLabel *label) {
    if (m_hView==NULL) m_hView = label;

    connect(this,   SIGNAL(pixmapReady(QPixmap)),
            label,  SLOT(setPixmap(QPixmap)),
            Qt::QueuedConnection)
}

/*! *****************************************************************
 * Trent das Kamerabild mit einem UI-Element (Label)
 *******************************************************************/
void UEyeCamera::disconnectLabel() {
    m_hView = NULL;
}

/*! *****************************************************************
 * Zeichnet das Aktuelle Bild der Kamera auf das Label
 *******************************************************************/
void UEyeCamera::updateLabel() {
    // Prüfen ob ein UI-Element verbunden ist -----------------------
    if (m_hView==NULL) return;

    int nRet;
    // Bestimmen welcher speicher gerade nicht benutzt wird ---------
    char  *pLast = NULL;
    char  *pMem  = NULL;
    int    dummy = 0;

    QImage image = QImage(QSize(m_nWidth, m_nHeight),
                          QImage::Format_RGB888);

    nRet  = is_GetActSeqBuf (m_hCam, &dummy, &pMem, &pLast);
    // Auslesen des letzten Sequenzbuffers --------------------------
    if (nRet == IS_SUCCESS) {
        int    id = m_hFrames.indexOf(pLast);
        char *img = m_hFrames.at(id);
        int   nID = m_nFrameIDs.at(id);
        // Blockieren des Speichers zum auslesen --------------------
        nRet = is_LockSeqBuf(m_hCam,nID,img);
        if (nRet != IS_SUCCESS) return;

        // Bild Punkt für Punkt Kopieren ----------------------------
        for (long i=0;i<m_nWidth*m_nHeight*3;i+=3) {
            image.bits()[i  ] = img[i  ];
            image.bits()[i+1] = img[i+1];
            image.bits()[i+2] = img[i+2];
        }

        // Blockierung des Speichers aufheben -----------------------
        is_UnlockSeqBuf(m_hCam,nID,img);
    }
    // Kamerabild an das Label übergeben ----------------------------
    emit pixmapReady(QPixmap::fromImage(image));

}

ich habe einfach mal alles gepostet da es vieleicht auch das zusammenspiel im Thread sein könnte. Schonmal vielen Dank random
 
Zuletzt bearbeitet:
Hi,

erstmal was ganz allgemeines. Auch wenn in der Doku die Beispiele es so zeigen, von QThread abzuleiten ist der falsche weg!

Ein Qt-Mitarbeiter befasst sich in diesem Blog-Eintrag mit der falschen Benutzung von QThread und erklärt wie es eigentlich gedacht ist und das die kommenden Dokumentationen dies korrigiert haben werden.

\edit: Wie ich gerade sehe, behandelt er genau dein Problem^^

Gruß
RudolfG
 
Zurück