C ++ Qt GUI更新

时间:2017-03-21 18:14:27

标签: c++ qt

我是Qt的新手,所以我遇到了GUI更新问题。 我有两个类:主线程中的ControlWidget和单独线程中的CameraController

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    CameraController *cameraController = new CameraController;;
    ControlWidget *main_window = new ControlWidget;
    Thread getImageThread; 
    cameraController->moveToThread(&getImageThread);
    getImageThread.start();
    QTimer get_images_timer;
    QObject::connect(&get_images_timer, SIGNAL(timeout()), cameraController, SLOT(onTimerOut()), Qt::QueuedConnection);
    QObject::connect(cameraController, SIGNAL(sendLabel(QImage)), main_window, SLOT(getImage(QImage)), Qt::QueuedConnection);
    QObject::connect(&get_images_timer, SIGNAL(timeout()), main_window, SLOT(update()), Qt::QueuedConnection);
    get_images_timer.start(2000);
    app.exec();
    return 0;
}

所以每2秒我想从相机线程中获取图像并将它们发送到主线程(动作发生,所以我在main_window对象上有QImage)。 然后我想把这个QImage放到cam1和cam2 QLabel。在这里,我被困住了:

首先:当我使用setPixmap()方法时,QLabel.width()QLabel.height()image.width()image.height()pixmap.width()和{{1}不同}}

第二:我无法想象pixmap.height()。如果我做QLabel没有真正发生。 this->ImageLayout->addWidget(cam1)也无济于事。

我有一个额外的GUI更新工作者吗?我究竟做错了什么?

更多信息的源代码:

CameraController.h

this->update

CameraController.cpp

class CameraController : public QObject
{
    Q_OBJECT 
private: 
    CoreApi::InstanceHandle g_hApi;
    CoreApi::DeviceCollectionHandle hDeviceCollection;
    CoreApi::DeviceHandle hDevice;
    CoreApi::CameraPortHandle first_cam;
    Common::FrameHandle frame;
    QPixmap pixmap;
    QImage image;
public: 
    CameraController();
    ~CameraController();
    QLabel outLabel;
public slots:
    void onTimerOut();
signals:
    QImage sendLabel(QImage image);
};

ControlWidget.h

CameraController::CameraController()
{
    try
    {
        this->g_hApi = CoreApi::Instance::initialize();
        this->hDeviceCollection = this->g_hApi->deviceCollection();
        this->hDevice = hDeviceCollection->device(0);
        this->first_cam = hDevice->cameraPort(0);
        first_cam->autoConfigure();
        first_cam->liveStart();
    }
    catch (GeneralException& e)
    {
    std::cout << e.what() << std::endl;
    }
}

CameraController::~CameraController()
{
}

void CameraController::onTimerOut()
{
    if (this->first_cam->liveFrameReady())
    {
        this->frame = first_cam->liveFrame();
        this->image =  QImage((uchar*)this->frame->buffer()->data(), this->frame->dataType()->width(), this->frame->dataType()->height(), QImage::Format::Format_RGB888);
        this->image = this->image.scaled(QSize(this->image.width()/10, this->image.height()/10));
        std::cout << "width = "<<this->image.width() << "height = " << this->image.height() << std::endl;
        emit sendLabel(this->image.copy());
    }
}

ControlWidget.cpp

class ControlWidget :public QDialog
{
    Q_OBJECT
private:
    QGLCanvas *osCanvas;
    QGridLayout *mainLayout;
    QGridLayout *buttonLayout;
    QVBoxLayout *imageLayout, *settingsLayout;
    QHBoxLayout *controlLayout;
    QListWidget *cameraListWidget, *devicesListWidget;
    QLabel *cameraListLabel, *devicesListLabel, *cameraSettingsLabel, *fpsLabel, *shutterLabel;
    QHBoxLayout *fpsLayout, *shutterLayout;
    QLineEdit *fpsEdit, *shutterEdit;
    QPushButton *saveButton, *saveSettingButton, *applySettingsButton, *chooseFolderButton;
    QTimer* m_timer;
public:
    ControlWidget(QWidget *parent = 0);
    ~ControlWidget();
    QLabel *cam1, *cam2;
    QImage *camera_1, *camera_2;
    void createWidgets();
public slots:
    void getImage(QImage new_frame);
    void displayImages();
signals: 
    void images_loaded();
private slots:
    void onTimeout()
    {
        qDebug() << "Worker::onTimeout get called from controlWidget timer and  ?: " << QThread::currentThreadId();
    };
};

2 个答案:

答案 0 :(得分:5)

好的,所以你在这里遇到一些设计问题:

  1. tmp_label已在堆栈上创建,并且会在displayImages方法结束时被销毁

  2. 每次收到新的相机框架时,您都会尝试使用this->imageLayout->addWidget(this->cam1);将QLabel添加回用户界面。改为在构建窗口小部件时添加一次,然后仅使用cam1->setPixmap(...)

  3. 也许我错过了,但我看不到你在QLabel中设置图像的位置。这通常使用QLabel::setPixmap

  4. 完成

    然后:

    • 当您依赖标准小部件时,不需要调用update(),当您设置像素图时,QLabel会自动更新
    • 您实际上不需要在C ++中使用this->
    • 我不知道你的Thread类下面有什么,但是当使用QThread时你不需要传递Qt::QueuedConnection参数来进行连接,这是自动完成的。
    • 要排除与如何实例化UI或如何使用布局相关的问题,请先使用基于静态Qt Designer .ui的界面进行实验
    • 您可以使用QPixmap::save("image.jpg")QImage::save("image.jpg")
    • 轻松测试您阅读的QPixmap和QImage的有效性

答案 1 :(得分:1)

除@basslo评论外,不要this->cam1 = &tmp_label;。当tmp_label被销毁(它是一个局部变量)时,它将从它所属的布局中删除,因此它将永远不会被实际显示。

使用this->cam1->setPixmap(...)来分配新图片并定义尺寸政策,以便将构造扩展到扩展(this answer提供有关它的更多信息)。