开发者

Using QT to view streaming images from camera

I have a software that sends JPGs over the network to a GUI client that is supposed to display those images. I basically want to display them to a qt window but I'm having problems with how qt displays开发者_如何学JAVA consecutive JPGs. I made a test to see if I'm getting the image correctly by printing it to a file and that checks out fine. Here's the main code:

int main(int argc, char *argv[]) {
    // initialize resources, if needed
    // Q_INIT_RESOURCE(resfile);

    QApplication app(argc, argv);
    CameraWindow cw;
    cw.show();
    //app.setActiveWindow(&cw);
    cw.getData();       // this paints the window  
    return app.exec();
}

Here's the code that initializes the widget:

class CameraWindow : public QDialog {
    Q_OBJECT
    public:
    bool serverConnected;
    void getData();
    CameraWindow()
    {
        imgl = new QLabel;
        widget.scrollImage->setWidget(imgl);
        widget.scrollImage->setBackgroundRole(QPalette::Dark);
    }
    QLabel *imgl;
    virtual ~CameraWindow();
    private:
    Ui::CameraWindow widget;
};

This is the relevant part of the code that is supposed to paint the image to the screen which is inside an infinite loop:

getData() called from main:

while (myrval < Header.imageSize) {
    myrval = myrval + recv(msgsock, (char*) ((int) buff + myrval),
        Header.imageSize- myrval, 0);
}

//buff contains the jpg at this point
QPixmap imgjpg;
imgjpg.loadFromData((const unsigned char*)buff, Header.imageSize, "JPG");
//scroll image is the parent that displays child
//in this case, the label
imgl->setPixmap(imgjpg);

I got this to work for just one image that was loaded from a file but when I use the same method for a set of streaming images, this doesn't work. I'm new to Qt so I'm sure I have a subtle mistake.

Many thanks!


Because you are in a infinite loop, the Qt may not have chance to handle event. Could you try to call QCoreApplication::processEvents after you setPixmap?


I'd recommend creating an ImageProvider class that alerts others that it has an image ready:

public class ImageProvider : QObject {
    Q_OBJECT
public:
    QPixmap getCurrentImage() const { /* retrieve current image */ }
signals:
    void newImageAvailable();
};

Now you'll need a class to display that, so let's call that an ImageDisplayer and assume that it has a label called imageLabel that has your current image set on it:

public class ImageDisplayer : QWidget {
    Q_OBJECT
    QLabel *imageLabel;
    ImageProvider *provider; 
public:
    ImageDisplayer(QWidget *parent, ImageProvider *imageProvider) {
        this->imageLabel = /* setup QPixmap */;
        this->imageProvider = imageProvider;
        connect(imageProvider, SIGNAL("newImageAvailable()"), SLOT("setNewImage()"));
    }
    public void setNewImage() {
        imageLabel->setPixmap(imageProvider->getCurrentImage());
        update(); // schedule the repaint
    }
};

The call to update will cause the repaint to happen as soon as Qt deems reasonable. This also allows skipped frames and other things (which you may not want).

Lastly, you'll want to make sure everything gets connected by your main widget:

public class MainWidget : QMainWindow {
    Q_OBJECT
    ImageDisplayer *imageDisplayer;
    ImageProvider *imageProvider;
public:
    void MainWidget() {
        this->imageProvider = new ImageProvider(/*your dependencies*/);
        this->imageDisplayer = new ImageDisplayer(this, imageProvider);
    }
}

And in main:

int main(int argc, char* argv[]) {
    QApplication app(argc, argv);
    MainWidget w;
    w.show();
    return app.exec();
}

This likely isn't the best-performing implementation, but it's simple and may work for your needs.


In addition to Mason Chang's answer - a better way to do this is to have the display be a slot and then call the slot from a timer.

A setTimer value of 0 is effectively a loop - it recalls as soon as the slot finishes, but still allows other processing.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜