How to maintain specific height to width ratio of widget in qt5? - c++

I tried overriding methods hasHeightToWidth() and heightToWidth() but it didn't work for some reason.
Is there some complete example that I can use?
Upd1:
class MyWidget : public QWidget {
Q_OBJECT
public:
MyWidget() {
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sizePolicy.setHeightForWidth(true);
setSizePolicy(sizePolicy);
}
bool hasHeightForWidth() const override {
std::cout << __FUNCTION__ << std::endl;
return true;
}
int heightForWidth(int w) const override {
std::cout << __FUNCTION__ << " " << w << std::endl;
return w;
}
QSize sizeHint() const override {
return QSize(100, heightForWidth(100));
}
};
MyWidget instances are inserted in QHBoxLayout.
I use qt5.
Debug std::cout's show that hasHeightForWidth and heightForWidth are called many times

Related

capture QVideoFrame and display it in QVideoWidget

I want capture from camera frames.
I setup ui, camera, and surface.
QtVideoWidgetsIssueTrack::QtVideoWidgetsIssueTrack(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QCamera* mCamera = new QCamera();
QMediaRecorder* recorder = new QMediaRecorder(mCamera);
QVideoEncoderSettings settings = recorder->videoSettings();
QMyAbstractVideoSurface* surface = new QMyAbstractVideoSurface();
settings.setResolution(640, 480);
settings.setQuality(QMultimedia::VeryHighQuality);
settings.setFrameRate(30.0);
settings.setCodec("video/mp4");
recorder->setVideoSettings(settings);
recorder->setContainerFormat("mp4");
mCamera->setCaptureMode(QCamera::CaptureViewfinder);
mCamera->setViewfinder(surface);
// Set layout
QGridLayout* layout = new QGridLayout();
QVideoWidget* videoWidget = new QVideoWidget;
videoWidget->show();
// Set layout in QWidget
QWidget* window = new QWidget();
layout->addWidget(videoWidget);
window->setLayout(layout);
// Set QWidget as the central layout of the main window
setCentralWidget(window);
bool o = recorder->setOutputLocation(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + "/" + "test_video"));
recorder->record();
mCamera->start();
qDebug() << o;
qDebug() << recorder->supportedVideoCodecs();
qDebug() << recorder->state();
qDebug() << recorder->error();
qDebug() << recorder->outputLocation();
}
QtVideoWidgetsIssueTrack::~QtVideoWidgetsIssueTrack()
{}
I have created QMyAbstractVideoSurface instance and set surface in camera.
#pragma once
#include <QtMultimedia/QAbstractVideoSurface>
class QMyAbstractVideoSurface : public QAbstractVideoSurface
{
Q_OBJECT
public:
explicit QMyAbstractVideoSurface(QObject* parent = 0);
~QMyAbstractVideoSurface();
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
bool present(const QVideoFrame& frame);
bool start(const QVideoSurfaceFormat& format);
void stop();
};
Now the problem is capture QVideoFrame from present method and display it in QVideoWidget.
Then add QVideoWidget to grid layout.
#include "QMyAbstractVideoSurface.h"
#include <QDebug>
#include <QBuffer>
QMyAbstractVideoSurface::QMyAbstractVideoSurface(QObject* parent) {
}
bool QMyAbstractVideoSurface::start(const QVideoSurfaceFormat& format) {
return QAbstractVideoSurface::start(format);
}
void QMyAbstractVideoSurface::stop() {
QAbstractVideoSurface::stop();
}
bool QMyAbstractVideoSurface::present(const QVideoFrame& frame) {
if (frame.isValid()) {
QVideoFrame cloneFrame(frame);
QAbstractVideoBuffer::HandleType handleType;
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
qDebug() << cloneFrame;
const QImage image(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat()));
QByteArray ba;
QBuffer bu(&ba);
//bu.open(QBuffer::ReadWrite);
bu.open(QIODevice::WriteOnly);
image.save(&bu, "PNG");
//bu.close();
//QString imgBase64 = ba.toBase64();
QString imgBase64 = QString::fromLatin1(ba.toBase64().data());
qDebug() << "image base64: " << imgBase64;
cloneFrame.unmap();
return true;
}
return true;
}
QList<QVideoFrame::PixelFormat> QMyAbstractVideoSurface::
supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
Q_UNUSED(handleType);
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555
<< QVideoFrame::Format_ARGB8565_Premultiplied
<< QVideoFrame::Format_BGRA32
<< QVideoFrame::Format_BGRA32_Premultiplied
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGR24
<< QVideoFrame::Format_BGR565
<< QVideoFrame::Format_BGR555
<< QVideoFrame::Format_BGRA5658_Premultiplied
<< QVideoFrame::Format_AYUV444
<< QVideoFrame::Format_AYUV444_Premultiplied
<< QVideoFrame::Format_YUV444
<< QVideoFrame::Format_YUV420P
<< QVideoFrame::Format_YV12
<< QVideoFrame::Format_UYVY
<< QVideoFrame::Format_YUYV
<< QVideoFrame::Format_NV12
<< QVideoFrame::Format_NV21
<< QVideoFrame::Format_IMC1
<< QVideoFrame::Format_IMC2
<< QVideoFrame::Format_IMC3
<< QVideoFrame::Format_IMC4
<< QVideoFrame::Format_Y8
<< QVideoFrame::Format_Y16
<< QVideoFrame::Format_Jpeg
<< QVideoFrame::Format_CameraRaw
<< QVideoFrame::Format_AdobeDng;
}
QMyAbstractVideoSurface::~QMyAbstractVideoSurface()
{}
it display me this
QVideoFrame(QSize(640, 480), Format_YUYV, NoHandle, ReadOnly, [no timestamp])
image base64: ""

pjsua2 hangs at makeCall() after 1-2 calls

I started writing application with Qt5, Im running pjsua2_demo.cpp from pjproject-2.9/pjsip-apps/src/samples/ in a QThread with infinite while(1) loop to leave pjsua2 running forever.
When I make 1-2 calls it blocks/hangs at the makeCall() function here:
call->makeCall(num.toStdString(), prm);
Also I want to know if im writing the code correctly. :)
This is my mainwindow.cpp
#include "./ui_mainwindow.h"
#include "pjsuathread.h"
PjsuaThread *pjsua_thread;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
pjsua_thread = new PjsuaThread(this);
connect(pjsua_thread, &PjsuaThread::resultReady, this, &MainWindow::handleResults);
connect(pjsua_thread, &PjsuaThread::resultReady2, this, &MainWindow::handleResults2);
connect(pjsua_thread, &PjsuaThread::finished, pjsua_thread, &QObject::deleteLater);
pjsua_thread->start();
ui->answerButton->setVisible(false);
ui->hangButton->setVisible(false);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handleResults(const QString &s)
{
ui->textEdit->setText(s);
}
void MainWindow::handleResults2(const QString &ss)
{
if(ss=="ringing")
{
ui->answerButton->setVisible(true);
ui->hangButton->setVisible(true);
}
}
void MainWindow::on_callButton_clicked()
{
pjsua_thread->number = "sip:2010#192.168.0.44";
pjsua_thread->state = "call";
ui->hangButton->setVisible(true);
}
void MainWindow::on_callButton2_clicked()
{
pjsua_thread->number = "sip:1001#192.168.0.44";
pjsua_thread->state = "call";
ui->hangButton->setVisible(true);
}
void MainWindow::on_hangButton_clicked()
{
pjsua_thread->state = "hangup";
ui->hangButton->setVisible(false);
ui->answerButton->setVisible(false);
}
void MainWindow::on_answerButton_clicked()
{
pjsua_thread->state = "answer";
ui->hangButton->setVisible(true);
ui->answerButton->setVisible(false);
}
this is my pjsuathread.cpp
#include <QString>
#include "pjsuathread.h"
#include "pjsua2_main.h"
PjsuaThread *pjt = NULL;
PjsuaThread::PjsuaThread(QObject *parent)
: QThread{parent}
{
pjt = this;
}
void PjsuaThread::run()
{
pjsua2_main();
}
and this is my pjsua2_main.cpp
#include "pjsua2_main.h"
#include <pjsua2.hpp>
#include <iostream>
#include <pj/file_access.h>
#define THIS_FILE "pjsua2_main.cpp"
using namespace pj;
Call *call = NULL;
class MyAccount;
class MyCall : public Call
{
private:
MyAccount *myAcc;
public:
MyCall(Account &acc, int call_id = PJSUA_INVALID_ID)
: Call(acc, call_id)
{
myAcc = (MyAccount *)&acc;
}
~MyCall()
{
}
virtual void onCallState(OnCallStateParam &prm);
virtual void onCallTransferRequest(OnCallTransferRequestParam &prm);
virtual void onCallReplaced(OnCallReplacedParam &prm);
virtual void onCallMediaState(OnCallMediaStateParam &prm);
};
class MyAccount : public Account
{
public:
std::vector<Call *> calls;
public:
MyAccount()
{}
~MyAccount()
{
std::cout << "*** Account is being deleted: No of calls="
<< calls.size() << std::endl;
for (std::vector<Call *>::iterator it = calls.begin();
it != calls.end(); )
{
delete (*it);
it = calls.erase(it);
}
}
void removeCall(Call *call)
{
for (std::vector<Call *>::iterator it = calls.begin();
it != calls.end(); ++it)
{
if (*it == call) {
calls.erase(it);
break;
}
}
}
virtual void onRegState(OnRegStateParam &prm)
{
AccountInfo ai = getInfo();
std::cout << (ai.regIsActive? "*** Register: code=" : "*** Unregister: code=")
<< prm.code << std::endl;
}
virtual void onIncomingCall(OnIncomingCallParam &iprm)
{
call = new MyCall(*this, iprm.callId);
CallInfo ci = call->getInfo();
std::cout << "*** Incoming Call: " << ci.remoteUri << " ["
<< ci.stateText << "]" << std::endl;
emit pjt->resultReady2("ringing");
calls.push_back(call);
}
};
void MyCall::onCallState(OnCallStateParam &prm)
{
PJ_UNUSED_ARG(prm);
CallInfo ci = getInfo();
std::cout << "*** Call: " << ci.remoteUri << " [" << ci.stateText << "]" << std::endl;
pjt->info+="*** Call: ";
pjt->info+=QString::fromStdString(ci.remoteUri);
pjt->info+=" [";
pjt->info+=QString::fromStdString(ci.stateText);
pjt->info+="]\n";
pjt->infoChanged=true;
if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
{
//pjt->remove_call=true;
myAcc->removeCall(this);
/* Delete the call */
delete this;
}
}
void MyCall::onCallMediaState(OnCallMediaStateParam &prm)
{
//PJ_UNUSED_ARG(prm);
CallInfo ci = getInfo();
AudioMedia aud_med;
try {
// Get the first audio media
aud_med = getAudioMedia(-1);
} catch(...) {
std::cout << "Failed to get audio media" << std::endl;
return;
}
AudioMedia& play_dev_med = Endpoint::instance().audDevManager().getPlaybackDevMedia();
AudioMedia& cap_dev_med = Endpoint::instance().audDevManager().getCaptureDevMedia();
pjt->info+="*** Connecting audio streams *** \n";
pjt->infoChanged=true;
// This will connect the sound device/mic to the call audio media
cap_dev_med.startTransmit(aud_med);
// And this will connect the call audio media to the sound device/speaker
aud_med.startTransmit(play_dev_med);
}
void MyCall::onCallTransferRequest(OnCallTransferRequestParam &prm)
{
/* Create new Call for call transfer */
prm.newCall = new MyCall(*myAcc);
}
void MyCall::onCallReplaced(OnCallReplacedParam &prm)
{
/* Create new Call for call replace */
prm.newCall = new MyCall(*myAcc, prm.newCallId);
}
MyAccount *acc(new MyAccount);
void make_call(QString num)
{
if(pjt->remove_call)
{
acc->removeCall(call);
/* Delete the call */
delete call;
pjt->remove_call=true;
}
std::cout << "here 1" << std::endl;
// Make outgoing call
call = new MyCall(*acc);
std::cout << "here 2" << std::endl;
acc->calls.push_back(call);
std::cout << "here 3" << std::endl;
CallOpParam prm(true);
std::cout << "here 4" << std::endl;
prm.opt.audioCount = 1;
prm.opt.videoCount = 0;
std::cout << "here 5" << std::endl;
call->makeCall(num.toStdString(), prm);
std::cout << "here 6" << std::endl;
}
static void mainProg1(Endpoint &ep)
{
// Init library
EpConfig ep_cfg;
ep_cfg.logConfig.level = 4;
ep_cfg.medConfig.threadCnt = 2;
ep.libInit( ep_cfg );
// Transport
TransportConfig tcfg;
tcfg.port = 5080;
ep.transportCreate(PJSIP_TRANSPORT_UDP, tcfg);
// Start library
ep.libStart();
std::cout << "*** PJSUA2 STARTED ***" << std::endl;
pjt->info="*** PJSUA2 STARTED ***\n";
emit pjt->resultReady(pjt->info);
// Add account
AccountConfig acc_cfg;
acc_cfg.idUri = "sip:2033#192.168.0.44";
acc_cfg.regConfig.registrarUri = "sip:192.168.0.44";
acc_cfg.sipConfig.authCreds.push_back( AuthCredInfo("digest", "*", "2033", 0, "PAss1234") );
try {
acc->create(acc_cfg);
} catch (...) {
std::cout << "Adding account failed" << std::endl;
}
//pj_thread_sleep(2000);
//make_call();
while(1)
{
if(pjt->state=="call")
{
pjt->state="";
std::cout << "############################# CALL ############################" << std::endl;
make_call(pjt->number);
std::cout << "###############################################################" << std::endl;
}
else if(pjt->state=="answer")
{
pjt->state="";
CallOpParam prm;
prm.statusCode = (pjsip_status_code)200;
call->answer(prm);
}
else if(pjt->state=="hangup")
{
pjt->state="";
CallOpParam prm;
prm.statusCode = (pjsip_status_code)486;
call->hangup(prm);
//ep.hangupAllCalls();
}
else if(pjt->infoChanged)
{
pjt->infoChanged=false;
emit pjt->resultReady(pjt->info);
}
else if(pjt->remove_call)
{
pjt->info+="Removing call...\n";
pjt->infoChanged=true;
acc->removeCall(call);
/* Delete the call */
delete call;
pjt->remove_call=false;
}
//ep.libHandleEvents(60);
}
// Hangup all calls
// pj_thread_sleep(4000);
// ep.hangupAllCalls();
// pj_thread_sleep(4000);
//
// Destroy library
std::cout << "*** PJSUA2 SHUTTING DOWN ***" << std::endl;
delete acc; /* Will delete all calls too */
}
int pjsua2_main()
{
int ret = 0;
Endpoint ep;
try {
ep.libCreate();
mainProg1(ep);
ret = PJ_SUCCESS;
} catch (Error & err) {
std::cout << "Exception: " << err.info() << std::endl;
ret = 1;
}
try {
ep.libDestroy();
} catch(Error &err) {
std::cout << "Exception: " << err.info() << std::endl;
ret = 1;
}
if (ret == PJ_SUCCESS) {
std::cout << "Success" << std::endl;
} else {
std::cout << "Error Found" << std::endl;
}
return ret;
}
and these are my header files:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
public slots:
void handleResults(const QString &s);
void handleResults2(const QString &ss);
private slots:
void on_callButton_clicked();
void on_callButton2_clicked();
void on_hangButton_clicked();
void on_answerButton_clicked();
};
#endif // MAINWINDOW_H
pjsuathread.h
#ifndef PJSUATHREAD_H
#define PJSUATHREAD_H
#include <QThread>
class PjsuaThread : public QThread
{
Q_OBJECT
public:
explicit PjsuaThread(QObject *parent = nullptr);
void run() override;
QString state;
QString info;
QString number;
bool infoChanged=false;
bool ringing=false;
bool remove_call=false;
signals:
void resultReady(const QString &s);
void resultReady2(const QString &ss);
};
#endif // PJSUATHREAD_H
and
pjsua2_main.h
#ifndef PJSUA2_MAIN_H
#define PJSUA2_MAIN_H
#include "pjsuathread.h"
int pjsua2_main();
extern PjsuaThread *pjt;
#endif // PJSUA2_MAIN_H
I solved the problem,
it was the version of pjproject.
Now I tried with v2.10 and everything fine.
v2.12 and v2.11 don't work because they give me undefined references when I compile the demo app.

QtCharts setRange issue

I want to display some data using QtCharts. When I set my data then nothing is displayed. I think the problem is with the setRange method.
Code:
chart.h:
#ifndef CHART_H
#define CHART_H
#include <QChart>
#include <QTimer>
#include <QAbstractAxis>
#include <QSplineSeries>
#include <QValueAxis>
#include <QDebug>
QT_CHARTS_BEGIN_NAMESPACE
class QSplineSeries;
class QValueAxis;
QT_CHARTS_END_NAMESPACE
QT_CHARTS_USE_NAMESPACE
class Chart: public QChart
{
Q_OBJECT
public:
Chart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
virtual ~Chart();
public slots:
void handleTimeout();
private:
QTimer m_timer;
QSplineSeries *m_series;
QStringList m_titles;
QValueAxis *m_axisX;
QValueAxis *m_axisY;
qreal m_step;
qreal m_x;
qreal m_y;
QList<double> testList;
};
#endif /* CHART_H */
chart.cpp:
#include "chart.h"
Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags):
QChart(QChart::ChartTypeCartesian, parent, wFlags),
m_series(0),
m_step(0),
m_x(1),
m_y(1)
{
m_axisX = new QValueAxis(this);
m_axisX->setLabelsVisible(false);
m_axisY = new QValueAxis(this);
m_axisY->setLabelsVisible(false);
connect(&m_timer, &QTimer::timeout, this, &Chart::handleTimeout);
m_timer.setInterval(1000);
m_series = new QSplineSeries(this);
QPen green(Qt::green);
green.setWidth(3);
m_series->setPen(green);
m_series->append(m_x, m_y);
legend()->hide();
addSeries(m_series);
setAxisX(m_axisX, m_series);
setAxisY(m_axisY, m_series);
m_axisX->setTickCount(5);
testList << 93.8436 << 777.797 << 2507.78 << 5999.44 << 6806.54 << 7481.16
<< 8008.5 << 8093.8 << 8161.83 << 8216.99
<< 8280.46 << 8328.4 << 8394.55 << 8469.84
<< 8500.65 << 8558.16 << 8660.9 << 8638.87
<< 8726.47 << 8715.25 << 8804.48 << 8793.86
<< 8839.42 << 8875.75 << 8938.24 << 8977.09
<< 9020.27 << 9046.7 << 9092.04 << 9121.58
<< 9155.36 << 9199.46;
axisX()->setRange(0, 100);
axisY()->setRange(-1, 100);
m_timer.start();
}
void Chart::handleTimeout()
{
qreal x = plotArea().width() / m_axisX->tickCount();
qreal y = (m_axisX->max() - m_axisX->min()) / m_axisX->tickCount();
m_x += y;
if (!testList.isEmpty()) {
m_y = testList.first();
testList.takeFirst();
}
qDebug() << "m_x: " << m_x << " " << "m_y: " << m_y;
m_series->append(m_x, m_y);
scroll(x, 0);
}
Chart::~Chart()
{
}
main.cpp:
#include "chart.h"
#include <QChartView>
#include <QApplication>
#include <QWidget>
#include <QHBoxLayout>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget window;
Chart *chart = new Chart;
//chart->setTitle("Dynamic spline chart");
chart->setAnimationOptions(QChart::AllAnimations);
QChartView chartView(chart);
chartView.setRenderHint(QPainter::Antialiasing);
chartView.resize(window.size());
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget(&chartView);
window.setLayout(layout);
window.setMinimumSize(810, 400);
window.show();
return a.exec();
}
Any ideas how to fix it? Thanks.
[Updated]
I have fixed the issue. Now it works well, but I need to set the axis rect background color.
Screenshot:
Any ideas how to set the axis background color? Thanks.
I have fixed the issue by using QtNetworkMonitor example from GitHub. The issue is resolved.

FLTK: Event when a window gets focus on MacOS

Using FLTK, I'm writing a desktop application which uses multiple windows. The application manages a list of open windows and shows them in the menu with these lines:
for( int i = 0; i < windows.size(); ++i ) {
menu->add(("&Windows/"+windows[i].name).c_str(), 0, MyMenuCallback);
}
Now I want to set a checkmark in front of the name of the top-most window:
flags = FL_MENU_TOGGLE|FL_MENU_VALUE;
menu->add(("&Windows/"+windows[i].name).c_str(), 0, MyMenuCallback, 0, flags);
I'm stuck at installing an event handler that gets called whenever the top-most window changes. I was hoping Fl::add_handler( &genericEventHandler ); would get called whenever focus changes, but that is not the case. So, my question is: How do I get notified, when the focus of my windows changes?
You should subclass Fl_Window to override its handle method to monitor FL_FOCUS and FL_UNFOCUS events. Here is a sample:
class MyWindow : public Fl_Window {
public:
MyWindow(int X,int Y,int W,int H, const char* title) : Fl_Window (X, Y, W, H, title) {}
int handle(int e) {
switch(e) {
case FL_FOCUS:
std::cout << "Window " << label() << " is focused" << std::endl;
break;
case FL_UNFOCUS:
std::cout << "Window " << label() << " has lost focus" << std::endl;
break;
}
return(Fl_Window::handle(e));
}
};
int main() {
MyWindow win1(100, 100, 200,200, "Window 1");
win1.show();
MyWindow win2(350, 100, 200,200, "Window 2");
win2.show();
return Fl::run();
}

QImage corrupts with OpenCV [duplicate]

This question already has answers here:
cv::Mat to QImage and back
(2 answers)
Closed 1 year ago.
I have a webcam demo with Qt and OpenCV. Basically it will show the webcam's feed, and when a button gets clicked, it starts a thread with a long (three-five seconds) thread.
The problem is that the QImage gets immediately corrupted as you can see here when I click the button, and I don't see the video feed anymore. The signals & slots work (I see the output in the console), but I cannot spot the problem here.
Can anyone help?
window::window() : QMainWindow(NULL, 0)
{
std::cout << "constructor start" << std::endl;
setWindowTitle("Video");
button = new QPushButton("Long Job");
connect(button, SIGNAL(clicked()), this, SLOT(longjob()));
image = new QLabel();
image->setAlignment(Qt::AlignCenter);
layout = new QVBoxLayout();
layout->addWidget(image);
layout->addWidget(button);
mainwidget = new QWidget();
mainwidget->setLayout(layout);
resize(800, 600);
setCentralWidget(mainwidget);
cap = cv::VideoCapture(0);
timer = new QTimer();
timer->setInterval(100);
timer->start();
connect(timer, SIGNAL(timeout()), this, SLOT(newframe()));
std::cout << "constructor end" << std::endl;
}
void window::newframe()
{
std::cout << "FRAME " << count++ << std::endl;
cv::Mat frame;
cap >> frame;
image->setPixmap(QPixmap::fromImage(showImage(frame))); // converts perfectly
}
void window::longjob()
{
std::cout << "START THREAD" << std::endl;
w = new worker();
connect(w, SIGNAL(resultReady(double)), this, SLOT(detected(double)));
w->start();
return;
}
void window::detected(double d)
{
disconnect(w, SIGNAL(resultReady(double)), this, SLOT(detected(double)));
std::cout << "DETECTED " << d << std::endl;
delete w;
frames.clear();
}
class worker : public QThread
{
Q_OBJECT
public:
worker();
~worker();
void run() Q_DECL_OVERRIDE;
signals:
void resultReady(double d);
};
worker::worker() : QThread()
{
}
worker::~worker()
{
std::cout << "THREAD EXIT" << std::endl;
}
void worker::run()
{
std::cout << "THREAD RUN" << std::endl;
double d = longOpenCVJob();
emit resultReady(d);
}
I would use this code for showImage():
QImage window::showImage(cv::Mat mat)
{
cv::Mat tmp;
mat.convertTo(tmp, CV_8U);
cvtColor(tmp, tmp, CV_BGR2RGB);
QImage img = QImage((const unsigned char *)(tmp.data), tmp.cols, tmp.rows, tmp.step, QImage::Format_RGB888);
return img;
}