PDA

View Full Version : 'QMessageBox::critical' : none of the 4 overloads could convert all the argument type



Sai Kamat
12th March 2014, 06:24
I want to display an error message whenever my independent thread encounters the word "alert1" in a specific .txt file. But I get the above error inside the monitorForAlerts() inside mythread.cpp file. The line expectedly executes if I were to place it inside dialog.cpp. So I guess this is due to non-inheritance of this object. Can you please advise me how to solve this error for the given code?

Here is the code:
dialog.h


#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QtCore>
#include "mythread.h"
namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
Q_OBJECT

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

public slots:

private:
Ui::Dialog *ui;

private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
};

#endif // DIALOG_H


mythread.h


#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QtCore>
#include <QDebug>
#include <QFile>
#include <Windows.h>
#include <QMessageBox>
#include <QTimer>
#define ALERTS_MESSAGE_STORAGE_PATH "E:\\QT1\\simpleGUIThread2\\simpleGUIThread2\\usbAl ert.txt"
#define TIMER_VALUE 500
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
void run();
QString name;
void monitorForAlerts();
int exec();

public slots:

signals:
void testSignal(QString message);

public slots:

};

#endif // MYTHREAD_H


dialog.cpp


#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}

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

void Dialog::on_pushButton_clicked()
{
ui->label->show();
}

void Dialog::on_pushButton_2_clicked()
{
ui->label->hide();
}


mythread.cpp


#include "mythread.h"
#include "dialog.h"
MyThread::MyThread(QObject *parent) :
QThread(parent)
{
}

void MyThread::run()
{
exec();
}

int MyThread::exec()
{
while(1)
{
monitorForAlerts();
emit(testSignal("hello world!!"));
sleep(1);
}
}

void MyThread::monitorForAlerts()
{
QString response = ALERTS_MESSAGE_STORAGE_PATH;
QFile resp(response);
resp.open(QIODevice::WriteOnly);
resp.close();
QFile resp1(response);
char buf[121];
char buf1[] = "alert1";
char buf2[] = "alert2";

resp1.open(QIODevice::ReadOnly);
while(resp1.size() == 0)
{
Sleep(3000);
}
qint64 lineLength = resp1.readLine(buf, sizeof(buf));
resp1.close();
if(strcmp(buf,buf1) == 0)
{
QFile::remove(ALERTS_MESSAGE_STORAGE_PATH);
qDebug()<<"warning 1!!";
QMessageBox::critical(this,tr("ERROR"),tr("Large change in illumination.\nPlease re-capture reference image.\n"));
}
if(strcmp(buf,buf2) == 0)
{
QFile::remove(ALERTS_MESSAGE_STORAGE_PATH);
qDebug()<<"warning 2!!";
QMessageBox::critical(this,tr("ERROR"),tr("The camera position has been moved or an object is obscuring its view.\nPlease check the device.\n"));
}
}


main.cpp


#include "dialog.h"
#include <QApplication>
#include "mythread.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);

MyThread mThread1;
mThread1.name = "mThread1";
mThread1.start();

Dialog w;
w.show();

return a.exec();
}

anda_skoa
12th March 2014, 08:31
You cannot access UI classes from a secondary thread. Only the main thread, the one running QApplication::exec() is allowed to do that.

One option that you have is to let the thread emit a signal that you connect to your dialog class and let the dialog class show the message box.

Cheers,
_

Sai Kamat
12th March 2014, 09:13
Hi anda_skoa,
I took your advice. I have created a signal that the thread will emit and connect it to a slot for QDialog. Please let me know if my understanding is correct, because I do not know where to implement the connect(), since the signal is declared in mythread.h and the slot in dialog.h. The connection type argument for connect is Qt::QueuedConnection, so that gui elements from another thread different than main-thread are NOT created. Is this statement correct? and where do I place this?


connect( mThread, SIGNAL(alertSignal(QString)), this, SLOT(alertSlot(QString)), Qt::QueuedConnection);

mythread.h


//....
signals:
void alertSignal(QString message);
//....

dialog.h


//....
public slots:
void alertSlot(QString message);
//....

mythread.cpp


//....
if(strcmp(buf,buf1) == 0)
{
QFile::remove(ALERTS_MESSAGE_STORAGE_PATH);
qDebug()<<"warning 1!!";
emit(alertSignal("alert1"));
}
else if(strcmp(buf,buf2) == 0)
{
QFile::remove(ALERTS_MESSAGE_STORAGE_PATH);
qDebug()<<"warning 2!!";
emit(alertSignal("alert2"));
}

dialog.cpp


//...
void Dialog::alertSlot(QString message)
{
if(strcmp(message, "alert1"))
QMessageBox::critical(this,tr("ERROR"),tr("Large change in illumination.\nPlease re-capture reference image.\n"));
else if(strcmp(message, "alert2"))
QMessageBox::critical(this,tr("ERROR"),tr("The camera position has been moved or an object is obscuring its view.\nPlease check the device.\n"));
}

Now if this were correct, how do i implement the connect() and in which file?

anda_skoa
12th March 2014, 12:31
This looks reasonable.

You can do the connect in main()


QObject::connect( &mThread, SIGNAL(alertSignal(QString)), &w, SLOT(alertSlot(QString)), Qt::QueuedConnection);


Cheers,
_

Lesiok
12th March 2014, 14:10
And the last parameter is not needed because its default value is Qt::AutoConnection which means that for objects from different threads it is Qt::QueuedConnection.

anda_skoa
12th March 2014, 16:51
And the last parameter is not needed because its default value is Qt::AutoConnection which means that for objects from different threads it is Qt::QueuedConnection.
True, however in this case both objects belong to the same thread. It will still work with auto connection because another check is which thread is executing the emit and that is a different thread then the owner of the reciever object.

Doesn't hurt to explicitly specify Qt::QueuedConnection though.

Cheers,
_

ChrisW67
12th March 2014, 23:11
GUI objects in threads aside, the original error message:

QMessageBox::critical' : none of the 4 overloads could convert all the argument
is caused by:


QMessageBox::critical(this,tr("ERROR"),tr("Large change in illumination.\nPlease re-capture reference image.\n"));

because the first argument, this, is not a pointer to a QWidget and cannot be converted to one.