[英]C++ Qt GUI update
我是Qt的新手,所以我被GUI更新卡住了。 我有2個類:主線程中的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()
和image.height()
或pixmap.width()
和pixmap.height()
。
第二:我無法可視化QLabel
。 如果我執行此操作- this->ImageLayout->addWidget(cam1)
什么都沒有發生。 this->update
也無濟於事。
我需要額外的GUI更新工作人員嗎? 我究竟做錯了什么?
源代碼以獲取更多信息:
CameraController.h
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);
};
CameraController.cpp
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.h
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();
};
};
ControlWidget.cpp
ControlWidget::ControlWidget(QWidget *parent)
{
this->createWidgets();
this->m_timer = new QTimer;
connect(this->m_timer, SIGNAL(timeout()),this, SLOT(update()));
m_timer->start(1000);
}
ControlWidget::~ControlWidget()
{
delete this->mainLayout;
}
void ControlWidget::createWidgets()
{
this->imageLayout = new QVBoxLayout;
this->cam1 = new QLabel;
this->cam2 = new QLabel;
this->imageLayout->addWidget(cam1);
this->imageLayout->addWidget(cam2);
this->setLayout(this->imageLayout);
this->show();
}
void ControlWidget::displayImages()
{
QLabel tmp_label ;
std::cout << "********************************************************************************" << std::endl;
std::cout <<" camera height = " <<this->camera_1->height() << " camera width = " << this->camera_1->width() << std::endl;
std::cout << "********************************************************************************" << std::endl;
QPixmap tmp_pixmap = QPixmap::fromImage(this->camera_1->copy());
std::cout << "PIXMAP WIDTH = " << tmp_pixmap.width() << "Pixmap Height = " << tmp_pixmap.height() <<std::endl;
std::cout << "LABELWIDTH = "<< tmp_label.width() << "LabelHeight = "<< tmp_label.height() << std::endl;
tmp_label.setGeometry(200, 200, tmp_pixmap.width(), tmp_pixmap.height());
tmp_label.show();
this->cam1 = &tmp_label;
this->cam2 = &tmp_label;
std::cout << "CAM1 Width = " <<this->cam1->width() << std::endl;
this->imageLayout->addWidget(this->cam1);
this->imageLayout->addWidget(this->cam2);
}
void ControlWidget::getImage(QImage img)
{
std::cout << "********************************************************************************" << std::endl;
std::cout << " img height = " << img.height() << " img width = " << img.width() << std::endl;
std::cout << "********************************************************************************" << std::endl;
this->camera_1 = &QImage(img);
this->camera_2 = &QImage(img);
this->displayImages();
}
好的,所以這里有一些設計問題:
tmp_label
在堆棧上創建,並且無論如何都會在displayImages
方法的末尾銷毀
每次收到新的相機框架時,您都嘗試使用this->imageLayout->addWidget(this->cam1);
將QLabels添加回您的UI this->imageLayout->addWidget(this->cam1);
。 而是在構造窗口小部件時添加一次,然后僅使用cam1->setPixmap(...)
。
也許我錯過了,但是我看不到您在QLabel中設置圖像的位置。 這通常是通過QLabel::setPixmap
接着:
update()
,QLabel在設置其像素圖時會自動更新 this->
Thread
類下有什么內容,但是當使用QThreads時,您不需要為連接傳遞Qt::QueuedConnection
參數,這是自動完成的 QPixmap::save("image.jpg")
或QImage::save("image.jpg")
輕松測試所讀取的QPixmap和QImage的有效性。 除了@basslo注釋之外,請勿執行此操作- this->cam1 = &tmp_label;
。 當tmp_label
被銷毀(它是一個局部變量)時,它也將從其所屬的布局中刪除,因此它永遠不會被實際顯示。
使用this->cam1->setPixmap(...)
代替分配新圖像,並定義大小策略,以從構造擴展到擴展( 此答案提供了有關它的更多信息)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.