Использование QT для просмотра потоковых изображений с камеры - PullRequest
0 голосов
/ 28 июня 2011

У меня есть программное обеспечение, которое отправляет JPG по сети клиенту с графическим интерфейсом, который должен отображать эти изображения. Я в основном хочу отобразить их в окне qt, но у меня возникают проблемы с тем, как qt отображает последовательные JPG. Я проверил, правильно ли я получаю изображение, печатая его в файл, и это хорошо. Вот основной код:

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();
}

Вот код, который инициализирует виджет:

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;
};

Это соответствующая часть кода, которая должна рисовать изображение на экране, который находится внутри бесконечного цикла:

getData () вызывается из 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);

Я получил это, чтобы работать только для одного изображения, которое было загружено из файла, но когда я использую тот же метод для набора потоковых изображений, это не работает. Я новичок в Qt, поэтому я уверен, что у меня есть небольшая ошибка.

Большое спасибо!

Ответы [ 3 ]

1 голос
/ 28 июня 2011

Я бы порекомендовал создать класс ImageProvider, который предупреждает других, что у него есть готовое изображение:

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

Теперь вам понадобится класс для отображения этого, поэтому давайте назовем его ImageDisplayer и предположим, что у него есть метка imageLabel, на которой установлено ваше текущее изображение:

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
    }
};

Вызов update приведет к перерисовке, как только Qt сочтет это разумным. Это также позволяет пропустить кадры и другие вещи (которые вы, возможно, не хотите).

Наконец, вам нужно убедиться, что все связано с вашим основным виджетом:

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);
    }
}

А в основном:

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

Вероятно, это не самая эффективная реализация, но она проста и может работать для ваших нужд.

1 голос
/ 28 июня 2011

Поскольку вы находитесь в бесконечном цикле, Qt может не иметь возможности обработать событие.Не могли бы вы попытаться вызвать QCoreApplication :: processEvents после установки setPixmap?

0 голосов
/ 28 июня 2011

В дополнение к ответу Мэйсона Чанга - лучший способ сделать это состоит в том, чтобы дисплей был слотом, а затем вызывал слот из таймера.

Значение setTimer, равное 0, фактически является циклом - оно вызывается, как только заканчивается слот, но все же допускает другую обработку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...