PDA

View Full Version : QCameraViewfinder behaves differently in Windows and Xubuntu.



feraudyh
15th July 2017, 21:50
Hi, I wanted to create a test project to use my webcam to take a still picture and save it as a file.
I'm using Qt 5.3.1 on Windows7 and Qt 5.5.1 on Xubuntu 14
The code is identical in both platforms, but in my Mainwindows application, I have to different ways of taking the picture:

The first way involves creating a QCamera, a QCameraViewfinder and a QCameraImageCapture from within the Mainwindow. One slot creates the camera and viewfinder which it displays as a separate window. The second slot attempts to capture the image so as to save to a file.


The second way is to create a separate dialog box which has the QCameraViewfinder inside a QLayout. Most of the dialog is designed with the QtDesigner inside QtCreator,
and the QCameraViewfinder is appended (by hand written code) as a widget to the vertical layout I have used to align a btCapture button and a stop button.


It's a surprise to me that the first method works on Xubuntu, but not on Windows: I get a message

failed to start
Stream did not open
in Windows (with a black viewfinder)
but a small and functional viewfinder in Xubuntu.
The problem with this is that I get a lot of

QWidget:: paintEngine: Should no longer be called
messages.

The second solution works in Windows without a problem, but on Xubuntu I get a lot of

QWidget:: paintEngine: Should no longer be called
messages.
I dont know if those messages signal danger!

Of course a nice small fully working example would be welcome.

Now here is the code. In the mainwindow.cpp file I have this


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_QCamera(NULL),
m_QCameraImageCapture(NULL),
m_QCameraViewfinder(NULL),
m_DialogViewer(NULL)
{
ui->setupUi(this);
m_DialogViewer = new DialogViewer(this);
connect(ui->actionCount_cameras,SIGNAL(triggered(bool)),this, SLOT(slotCountCameras()));
connect(ui->actionViewfinder,SIGNAL(triggered(bool)),this,SLOT (slotViewfinder1()));
connect(ui->actionCapture_Image,SIGNAL(triggered(bool)),this,S LOT(slotCaptureImage1()));
connect(ui->actionCapture_Image2,SIGNAL(triggered(bool)),this, SLOT(slotCaptureImage2()));
connect(ui->actionViewer_dialog,SIGNAL(triggered(bool)),this,S LOT(slotDialogViewer()));
}

MainWindow::~MainWindow()
{
delete ui;
if(m_QCamera)
delete m_QCamera;
if(m_QCameraImageCapture)
delete m_QCameraImageCapture;
if(m_QCameraViewfinder)
delete m_QCameraViewfinder;
if(m_DialogViewer)
delete m_DialogViewer;
}
void MainWindow::tracemsg(QString s)
{
ui->plainTextEdit1->append(s);
}

void MainWindow::slotCountCameras()
{
int camera_count = QCameraInfo::availableCameras().count();
tracemsg(tr("Number of cameras connected = %1").arg(camera_count));
for(int i = 0; i < camera_count;i++)
{
QCameraInfo caminfo = QCameraInfo::availableCameras().at(i);
tracemsg(tr("device name = %1").arg(caminfo.deviceName()));
tracemsg(tr("description = %1").arg(caminfo.description()));

}
}

// adaptation of code in http://doc.qt.io/qt-5/cameraoverview.html

void MainWindow::slotViewfinder1()
{
m_QCamera = new QCamera;
m_QCamera->setCaptureMode(QCamera::CaptureStillImage);
m_QCameraViewfinder = new QCameraViewfinder;
m_QCamera->setViewfinder(m_QCameraViewfinder);
m_QCameraViewfinder->show();
m_QCamera->start(); // to start the viewfinder
}

void MainWindow::slotCaptureImage1()
{

if(m_QCameraImageCapture)
delete m_QCameraImageCapture;
m_QCameraImageCapture = new QCameraImageCapture(m_QCamera);
m_QCameraImageCapture->setCaptureDestination(QCameraImageCapture::Capture ToFile);
tracemsg(tr("Codec used = %1").arg(m_QCameraImageCapture->encodingSettings().codec()));

connect(m_QCameraImageCapture,SIGNAL(imageCaptured (int,QImage)),this, SLOT(slotSaveImage1(int,QImage)));
if(m_QCameraImageCapture->isAvailable())
{
m_QCameraImageCapture->capture("");
}
else
{
tracemsg(tr("Capture not available"));
}

}

void MainWindow::slotCaptureImage2()
{

if(m_QCameraImageCapture)
delete m_QCameraImageCapture;

m_QCameraImageCapture = new QCameraImageCapture(m_QCamera);
m_QCameraImageCapture->setCaptureDestination(QCameraImageCapture::Capture ToFile);
tracemsg(tr("Codec used = %1").arg(m_QCameraImageCapture->encodingSettings().codec()));
if(m_QCameraImageCapture->isAvailable())
{
m_QCameraImageCapture->capture("Portrait2.jpg");
}
else
{
tracemsg(tr("Capture not available"));
}
}

void MainWindow::slotSaveImage1(int id, QImage img)
{
tracemsg(tr("id save image received %1").arg(id));
img.save(tr("Portrait1.jpg"),"JPEG") ;
}

void MainWindow::slotDialogViewer()
{
m_DialogViewer->show();
}


Here is the code of DialogViewer


#include <QCamera>
#include <QMessageBox>
#include <QCameraViewfinder>
#include <QCameraImageCapture>

#include "dialogviewer.h"
#include "ui_dialogviewer.h"

DialogViewer::DialogViewer(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogViewer),
m_QCamera(NULL),
m_QCameraImageCapture(NULL),
m_QCameraViewfinder(NULL)
{

ui->setupUi(this);
QSizePolicy policy(QSizePolicy::Preferred,QSizePolicy::Preferr ed,QSizePolicy::DefaultType);

m_QCamera = new QCamera(this);
m_QCameraViewfinder = new QCameraViewfinder(this);
m_QCameraViewfinder->setBaseSize(600,800);
m_QCameraViewfinder->setSizePolicy(policy);
m_QCamera->setViewfinder(m_QCameraViewfinder);
ui->verticalLayout->addWidget(m_QCameraViewfinder);
m_QCamera->start(); // to start the viewfinder

}
void DialogViewer::tracemsg(QString s)
{
QMessageBox::critical(this,tr("error"),s);
}

DialogViewer::~DialogViewer()
{
delete ui;
}

void DialogViewer::on_btCapture_clicked()
{
m_QCameraImageCapture = new QCameraImageCapture(m_QCamera);
m_QCameraImageCapture->setCaptureDestination(QCameraImageCapture::Capture ToFile);

//connect(m_QCameraImageCapture,SIGNAL(imageCaptured (int,QImage)),this, SLOT(slotSaveImage1(int,QImage)));
if(m_QCameraImageCapture->isAvailable())
{
QString file("portrait_from_dialog.jpg");
m_QCameraImageCapture->capture(file);
}
else
{
tracemsg(tr("Capture not available"));
}
}

void DialogViewer::on_stop_clicked()
{
close();
}


For completeness here is Mainwindow.h


#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class QCamera;
class QCameraViewfinder;
class QCameraImageCapture;
class DialogViewer;

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void tracemsg(QString s);
void slotCountCameras();
void slotViewfinder1();
void slotCaptureImage1();
void slotCaptureImage2();
void slotSaveImage1(int id, QImage img);
void slotDialogViewer();

private:
Ui::MainWindow *ui;
QCamera *m_QCamera;
QCameraViewfinder *m_QCameraViewfinder;
QCameraImageCapture *m_QCameraImageCapture;
DialogViewer *m_DialogViewer;
};

The code of Dialogviewer.h


#include <QDialog>
class QCamera;
class QCameraViewfinder;
class QCameraImageCapture;
namespace Ui {
class DialogViewer;
}

class DialogViewer : public QDialog
{
Q_OBJECT

public:
explicit DialogViewer(QWidget *parent = 0);
~DialogViewer();

private slots:
void on_btCapture_clicked();

void on_stop_clicked();

private:
Ui::DialogViewer *ui;
QCamera *m_QCamera;
QCameraViewfinder *m_QCameraViewfinder;
QCameraImageCapture *m_QCameraImageCapture;
void tracemsg(QString s);
};

feraudyh
16th July 2017, 15:04
OK, I have a partial answer to my problem above:
The constructor of DialogViewer which is called in the Mainwindow above is "competing" with the viewer that can be opened from the MainWindow menus, in that they both try to open a video stream.
If I comment out
m_DialogViewer = new DialogViewer(this); from the MainWindow constructor then I can view the video stream via

MainWindow::slotViewfinder1();

But this does not tell me why I get those

QWidget:: paintEngine: Should no longer be called
messages on Xubuntu.