Unable to find the slot of arduino though Qt - c++

#include "dialog.h"
#include "ui_dialog.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QtWidgets>
#include <QString>
#include <string>
#include <QObject>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
//ui->degree_lcdNumber->display("---");
// ui->distance_lcdNumber->display("---");
arduino_is_available = false;
port_name = "";
arduino =new QSerialPort;
serialBuffer = "";
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
if(serialPortInfo.hasVendorIdentifier() &&serialPortInfo.hasProductIdentifier()){
if(serialPortInfo.vendorIdentifier() == arduino_uno_vendorid){
if(serialPortInfo.productIdentifier()== arduino_uno_productid){
port_name = serialPortInfo.portName();
arduino_is_available = true;
}
}
}
}
if(arduino_is_available){
//open and configure the port
arduino->setPortName(port_name);
arduino->open(QSerialPort::ReadOnly);
arduino->setBaudRate(QSerialPort::Baud9600);
arduino->setDataBits(QSerialPort::Data8);
arduino->setParity(QSerialPort::NoParity);
arduino->setStopBits(QSerialPort::OneStop);
arduino->setFlowControl(QSerialPort::NoFlowControl);
QObject::connect(arduino,SIGNAL(readyRead()),this,SLOT(&serialReceived()));
}else{
//give error message
QMessageBox::warning(this,"Port Error","Couldn't find the Arduino!");
}
}
Dialog::~Dialog()
{
if(arduino->isOpen()){
arduino->close();
}
delete ui;
}
void Dialog::serialReceived(){
qDebug()<<"works" ;
QStringList bufferSplit = serialBuffer.split(".");
serialData = arduino->readAll();
serialBuffer += QString::fromStdString(serialData.toStdString());
serialBuffer = ",";
qDebug()<<bufferSplit;
}
void Dialog::updateLCD(const QString sensor_reading){
// ui->degree_lcdNumber->display(sensor_reading);
}
(.h)
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QSerialPort>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
QSerialPort *arduino;
static const quint16 arduino_uno_vendorid =9025;
static const quint16 arduino_uno_productid =67;
void updateLCD(const QString);
void serialReceived();
QString port_name;
//void readSerial();
QByteArray serialData;
QString serialBuffer;
bool arduino_is_available;
};
#endif // DIALOG_H
I just started the Qt. I want to connect Qt with arduino serially. I am reading the data but I am not able to connect with arduino slot.
I am getting a message after compilation. The message is QObject::connect: No such slot Dialog::&serialReceived() in ..\serial_sensor\dialog.cpp:45
QObject::connect: (receiver name: 'Dialog').
Can I know why?

As per the Qt Signals and Slot documentation, the Qt signals and slots have to be declared under signals: and public slots: respectively.
Why do we do that ?
Since slots are normal member functions, they follow the normal C++ rules when called directly. However, as slots, they can be invoked by any component, regardless of its access level, via a signal-slot connection. This means that a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class.( as per Qt Documentation)
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
public slots :
void serialReceived();
signals :
// Declare Signals here.
private:
// other private declarations.
};

The reason your connection is failing is that your connect syntax is wrong. Either you have mixed Qt's functor and string based connections or accidentally added & in front of serialReceived. Below you can find two ways to do your connection. The first one is preferred. You can read more from here. Because Dialog is QObject based class you can just call connect.
Functor based connection:
connect(arduino, &QSerialPort::readyRead, this, &Dialog::serialReceived);
String based connection:
connect(arduino, SIGNAL(readyRead()), this, SLOT(serialReceived()));
If you are using Qt4 you have to use slots in your declaration. In Qt5 slots is not strictly required for connections but it should still be used. If you don't use it you can't use introspection. You can't e.g. call QMetaObject::invokeMethod. So, in short add slots to your header file as others have already suggested.
public slots:
void serialReceived();

Related

How to get live variable updates on a statusbar in C++ with Qt's signals and slots?

I am using a proprietary driver API in my C++ / Qt application. There is an object named "status" which is essentially an integer value, that can be used to monitor errors. A value of 0 indicates all is fine, a negative value is a specific error. I would like to program a statusbar (using Qt's QStatusBar) which will give me live updates with the "status" current value as I execute parts of the code. A simplified example of what I currently have:
DriverInterfaceClass.h
#ifndef DRIVERINTERFACECLASS_H
#define DRIVERINTERFACECLASS_H
#include <QObject>
#include "multicam.h"
class DriverInterfaceClass : public QObject
{
Q_OBJECT
public:
DriverInterfaceClass(QObject *parent = nullptr);
~DriverInterfaceClass();
private:
void setStatus(int value);
private:
MCSTATUS status;
signals:
void statusChanged(const QString& status, int timeout);
};
#endif // DRIVERINTERFACECLASS_H
DriverInterfaceClass.cpp
#include "driverinterfaceclass.h"
DriverInterfaceClass::DriverInterfaceClass(QObject *parent)
: QObject(parent)
{
setStatus(McOpenDriver(NULL));
status = McSetParamStr(MC_CONFIGURATION, MC_ErrorLog, "error.log");
}
DriverInterfaceClass::~DriverInterfaceClass()
{
setStatus(McCloseDriver());
}
void DriverInterfaceClass::setStatus(int value)
{
status = value;
QString statusStr = QString::number(status);
emit statusChanged(statusStr, 0);
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "driverinterfaceclass.h"
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;
DriverInterfaceClass *driver;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
driver = new DriverInterfaceClass(this);
connect(driver, &DriverInterfaceClass::statusChanged, ui->statusbar, &QStatusBar::showMessage);
}
MainWindow::~MainWindow()
{
delete ui;
}
I have a problem figuring out how to update the statusbar with the value of the "status" variable. I am not getting any messages in my statusbar with this code. Perhaps I am missing something in the way I initialize my variable?
Cause
The statusChanged signal suffers from an unperceived existence. In other words, the driver object screams - STATUS CHAAAAAAANGED!!!!, but no one hears it. Here is why.
Your code is executed in the following order:
driver = new DriverInterfaceClass(this);
Then, as part of the constructor:
setStatus(McOpenDriver(NULL));
status = McSetParamStr(MC_CONFIGURATION, MC_ErrorLog, "error.log");
Only then is the connect statement executed:
connect(driver, &DriverInterfaceClass::statusChanged, ui->statusbar, &QStatusBar::showMessage);
Obviously, the signal is emited by setStatus BEFORE it is connected to the slot of ui->statusbar.
Note: You also set the value of status directly, without calling setStatus, i.e. status = McSetParamStr(..., thus the signal is not emited at all. However, calling setStatus instead would not help, because of the same reason as above.
Moving connect before new would cause a compiler error, because you cannot connect to something, which does not exist.
Solution
Do not emit signals from constructors. Do it when an event occurs.
To satisfy your invariant "emit signal whenever status is set" you need to use setStatus(McSetParamInt(... whatever)); method, don't modify status = xxx; directly (apart from the body of setStatus method). Then just change your setter function a bit to also emit the information about desired message to be displayed on the QStatusBar:
void DriverInterfaceClass::setStatus(int value)
{
if (status != value)
{
status = value;
emit statusChanged(myStatusValueToString(status));
}
}
where signal decl should be:
signals:
void statusChanged(const QString& msg);
and your myStatusValueToString just a simple mapping:
QString myStatusValueToString(int status)
{
if (status == 0) return "OK";
... etc ...
}
The connection should look like:
QObject::connect(driver, &DriverInterfaceClass::statusChanged, statusBar, &QStatusBar::showMessage);

Can't conect two frames with custom signals

I'm trying to connect two frames with a custom signal but I'm not really getting it.
This code is just an example of what im trying to do in my program, my objective is to transfer data between frames.
Files:
(sender)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
signals:
void send();
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
void on_pushButton_clicked();
};
#endif // MAINWINDOW_H
On "mainwindow.cpp" I've got the void on_pushButton_clicked() that emits the signal and shows the new frame:
private slot void:
void MainWindow::on_pushButton_clicked()
{
emit send();
Dialog sw;
sw.setModal(true);
sw.exec();
}
(receiver):
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QDebug>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog();
private slots:
void receive();
private:
Ui::Dialog *ui;
int a;
};
#endif // DIALOG_H
and the .cpp:
#include "dialog.h"
#include "ui_dialog.h"
#include "mainwindow.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
a=0;
MainWindow w;
connect(&w, SIGNAL(send()), this, SLOT(receive()));
qDebug() << a;
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::receive(){
qDebug() << "ola";
a++;
}
Conclusion:
So basicly the function Dialog doesn't print the qDebug(), and 'a' is still 0, so I conclude that the connection isn't set/executed.
Thanks all,
Best regards,
Dylan Lopes.
edit: Wrote a conclusion on the end of the post.
Consider the code in your Dialog constructor...
MainWindow w;
connect(&w, SIGNAL(send()), this, SLOT(receive()));
This creates a locally scoped MainWindow on the stack and connects its send() signal to the Dialog's receive() slot. But the MainWindow -- and, hence, the connection -- will be destroyed as soon as the Dialog constructor has completed.
In addition, looking at MainWindow::on_pushButton_clicked...
void MainWindow::on_pushButton_clicked()
{
emit send();
Dialog sw;
sw.setModal(true);
sw.exec();
}
You emit the send() signal before constructing the Dialog.
I don't really know enough about what you're trying to achieve to provide a definitive answer, but in the interests of getting some kind of signal/slot interaction you might want to do the following: change the Dialog constructor to...
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
a=0;
qDebug() << a;
}
And change MainWindow::on_pushButton_clicked to...
void MainWindow::on_pushButton_clicked()
{
Dialog sw;
connect(this, &MainWindow::send, &sw, &Dialog::receive);
emit send();
sw.setModal(true);
sw.exec();
}
That should at least result in Dialog::receive being invoked and you can work from there.
Connection between a signal and a slot doesn't mean that the signal function will be triggered.
You still need to emit your signal so that a gets updated.
Creating an empty slot isn't working either, as slots are the receiving point of a signal. In this case, on_pushButton_clicked() gets triggered whent he push button is clicked. This doesn't trigger send unless you call EMIT(send()) (IIRC, you emit a signal with EMIT, is that still the case?).

Qt - connecting a signal/slot in a triggered action

I'm using Qt 5 on a Windows and building a GUI App with multiple QDialog classes. I am trying to connect a signal from a QDialog in a triggered action of the QMainWindow class after instances of both have been created. I have read the documentation on Qt here: http://doc.qt.io/qt-4.8/signalsandslots.html and here: https://wiki.qt.io/New_Signal_Slot_Syntax. I have also read through many questions on stackoverflow that have helped correct some of the initial errors I was getting, but haven't helped me solve this problem.
The error I keep getting is:
"expected primary-expression before ',' token"
I have tried both the old syntax for connect
connect(sender, SIGNAL (valueChanged(QString,QString)),
receiver, SLOT (updateValue(QString)) );
and the new syntax (which is shown in the .cpp file below)
connect(sender, &Sender::valueChanged,
receiver, &Receiver::updateValue );
The MainWindow is created in the main.cpp and the 2nd dialog is created on_action_someAction_triggered(), so I know that the instances I am referencing exist. Is there a better way for me to connect the SIGNAL and the SLOT?
Here is the code I am working with (minus the extra unrelated code).
mainwindow .h:
#include <QMainWindow>
#include "shipdia.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void loadSelectedShip(QString shipName);
private slots:
void on_actionNew_Ship_triggered();
private:
Ui::MainWindow *ui;
shipdia *sDialog;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextStream>
#include <QObject>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionNew_Ship_triggered()
{
sDialog = new shipdia(this);
QObject::connect(&shipdia, //this is were I attempt to
&shipdia::sendShip, //connect the signal/slot
this,&MainWindow::loadSelectedShip); //but always get an error
sDialog ->show();
}
void MainWindow::loadSelectedShip(QString shipName)
{
... do something ... //this code works, but the signal is never received
}
qdialog.h
#ifndef SHIPDIA_H
#define SHIPDIA_H
#include "functions.h"
#include <QDialog>
namespace Ui {
class shipdia;
}
class shipdia : public QDialog
{
Q_OBJECT
public:
explicit shipdia(QWidget *parent = 0);
~shipdia();
private slots:
void on_pushButton_2_clicked();
signals:
void sendShip(QString shipName);
private:
Ui::shipdia *ui;
};
#endif // SHIPDIA_H
qdialog.cpp
#include "shipdia.h"
#include "ui_shipdia.h"
#include <QObject>
#include <QMessageBox>
#include <QTextStream>
#include <QDir>
shipdia::shipdia(QWidget *parent) :
QDialog(parent),
ui(new Ui::shipdia)
{
ui->setupUi(this);
}
shipdia::~shipdia()
{
delete ui;
}
void shipdia::sendSelectedShip(QString shipName)
{
emit sendShip(shipName); //I previously just emitted sendSelectedShip,
//but separating the function did not fix it.
}
void shipdia::on_pushButton_2_clicked()
{
//Code below functions up to next comment
QString shipName = ui->line_23->text();
shipName = QDir::currentPath() + "/shipFolder/" + shipName + ".txt";
QFile shipFile(shipName);
QStringList stringList;
if (shipFile.open(QIODevice::ReadOnly))
{
QTextStream in(&shipFile);
while(!in.atEnd())
{
QString line = in.readLine();
if(line.isNull())
break;
else
stringList.append(line);
}
shipFile.close();
}
//Code above functions ^
sendSelectedShip(shipName); //this line does not produce an error
}
I think, the code should be
sDialog = new shipdia(this);
QObject::connect(sDialog,
&shipdia::sendShip,this,&MainWindow::loadSelectedShip);
and it should be placed in the constructor of the MainWindow, right after ui->setupUi(this); and the on_actionNew_Ship_triggered() function should look like this:
void MainWindow::on_actionNew_Ship_triggered()
{
sDialog ->show();
}
In your original code, a new instance of shipdia will be created everytime the on_actionNew_Ship_triggered() is called. That should be avoided.
Hope this helps.

Qt multithreaded email : QObject: Cannot create children for a parent that is in a different thread

I have found an old thread that came close to answering this very question for me, its link can be found here QObject: Cannot create children for a parent that is in a different thread .
I know this is an old thread, but I am having a hard time following where to put the signals and slots in my situation. I am writing a program that will send out alerts via email, and I want them to be run in threads so they don't interrupt the main program and each other. I created an EmailThread class that inherits from QThread and implements the run() method. I have another class, Smtp.cpp, that successfully sends emails out but only in the main thread. I would like to create an instance of the Smtp class in each EmailThread for each address that should receive an email. I also have a namespace that handles all my database information. I want to be able to send information from my database to all the entered email addresses if something goes wrong. So which class gets the slots and which one emits the signals? And where would I place them, code examples to help me figure it out would be greatly appreciated.
//EmailThread Header
#ifndef EMAILTHREAD_H
#define EMAILTHREAD_H
#include <QThread>
#include "smtp.h"
class EmailThread : public QThread
{
public:
explicit EmailThread(QString to, QString from, QString subject, QString message);
signals:
public slots:
protected:
void run();
private:
Smtp * emailer;
QString to;
QString from;
QString subject;
QString message;
};
#endif // EMAILTHREAD_H
//EmailThread.cpp
#include "emailthread.h"
EmailThread::EmailThread(QString emailTo, QString emailFrom, QString emailSubject, QString emailMessage)
{
emailer = new Smtp("myaddress#email.com","myPassword", "secure.emailsrvr.com",465, 300000);
to = emailTo;
from = emailFrom;
subject = emailSubject;
message = emailMessage;
}
void EmailThread::run(){
emailer->sendMailNoAttachments(from,to, subject, message);
}
Called Email
EmailThread * newEmailThread = new EmailThread("myaddress#email.com","myaddress#email.com", "Subject Test", "This is the message string");
newEmailThread->start();
and I get the same error as above, where the parent and child thread are not the same. Here is the full error :
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSslSocket(0xc6dde0), parent's thread is QThread(0xf52410), current thread is QThread(0xc619c8)
QObject::connect: Cannot queue arguments of type 'QAbstractSocket::SocketState'
(Make sure 'QAbstractSocket::SocketState' is registered using qRegisterMetaType().)
Thank you for your consideration!
The method call to sendMainNoAttachments happens in the run method of your EmailThread class, which means it is correctly happening on another thread. However, your error stems from the fact that your emailer is getting created on the main/GUI thread.
This is because a QThread should be thought of as a "thread manager" class, and as such only its run method operates on the thread it manages. This means its constructor is executed on the thread that called it.
To overcome this, you can create your emailer in your run method, if you don't have problems with creating a new one every time. However, I'd instead highly recommend changing to a different usage of QThread, which is recommended when you want to have interactions between objects on separate threads.
You subclass QObject and move the function you want to perform in a thread to a slot within it. Then you use QObject::moveToThread to move the object to the thread. If any of its slots are signalled from a queued connection (which is automatic if the connection happens with an object that has been moved to another thread), they will be executed on that thread. Note that direct function calls to your worker object will still be executed on the main thread. You can read more about this in documentation for QThread.
First, you can create a standard QThread. We can use your Smtp class if it is type QObject. If it's not, you can create a wrapper and route signals through it. Next, you'll use moveToThread to move your Smtp instance to the new thread. Then, you'll need to connect a signal with your message contents to a slot that sends your mail on to your Smtp class.
Here's some example code detailing a possible solution.
Mailer.cpp
#include "Mailer.hpp"
Mailer::Mailer(QObject* parent) :
QObject(parent), emailer(45, 300000), thread(this) {
emailer.moveToThread(&thread);
thread.start();
w.show();
connect(&w, &MainWindow::sendMail,
&emailer, &Smtp::sendMailNoAttachments);
}
Mailer.hpp
#ifndef MAILER_HPP
#define MAILER_HPP
#include "Smtp.hpp"
#include "MainWindow.hpp"
#include <QObject>
#include <QThread>
#include <memory>
class Mailer : public QObject {
Q_OBJECT
public:
explicit Mailer(QObject* parent = nullptr);
private:
Smtp emailer;
QThread thread;
MainWindow w;
};
#endif // MAILER_HPP
Smtp.cpp
#include "Smtp.hpp"
Smtp::Smtp(int port, int number, QObject* parent)
: QObject(parent) {
}
void Smtp::sendMailNoAttachments(const QString& emailTo,
const QString& emailFrom,
const QString& emailSubject,
const QString& emailMessage) {
// Send that email!
}
Smtp.hpp
#ifndef SMTP_HPP
#define SMTP_HPP
#include <QObject>
class Smtp : public QObject {
Q_OBJECT
public:
explicit Smtp(int port, int number, QObject* parent = nullptr);
public slots:
void sendMailNoAttachments(const QString& emailTo,
const QString& emailFrom,
const QString& emailSubject,
const QString& emailMessage);
};
#endif // SMTP_HPP
MainWindow.cpp
#include "MainWindow.hpp"
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent) {
QWidget* centralWidget = new QWidget(this);
QLabel* toLabel = new QLabel(QStringLiteral("To: "));
toLineEdit = new QLineEdit(centralWidget);
QLabel* fromLabel = new QLabel(QStringLiteral("From: "));
fromLineEdit = new QLineEdit(centralWidget);
QLabel* subjectLabel = new QLabel(QStringLiteral("Subject: "));
subjectLineEdit = new QLineEdit(centralWidget);
QLabel* messageLabel = new QLabel(QStringLiteral("Message: "));
messageTextEdit = new QTextEdit(centralWidget);
QPushButton* mailButton = new QPushButton(centralWidget);
mailButton->setText(QStringLiteral("Send Mail"));
QVBoxLayout* layout = new QVBoxLayout(centralWidget);
layout->addWidget(toLabel);
layout->addWidget(toLineEdit);
layout->addWidget(fromLabel);
layout->addWidget(fromLineEdit);
layout->addWidget(subjectLabel);
layout->addWidget(subjectLineEdit);
layout->addWidget(messageLabel);
layout->addWidget(messageTextEdit);
layout->addWidget(mailButton);
this->setCentralWidget(centralWidget);
connect(mailButton, &QPushButton::clicked, this, &MainWindow::prepareMail);
}
void MainWindow::prepareMail() {
emit sendMail(toLineEdit->text(), fromLineEdit->text(),
subjectLineEdit->text(), messageTextEdit->toPlainText());
}
MainWindow.hpp
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
#include <QMainWindow>
#include <QLineEdit>
#include <QTextEdit>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = nullptr);
signals:
void sendMail(const QString& to, const QString& from,
const QString& subject, const QString& message);
public slots:
void prepareMail();
private:
QLineEdit* toLineEdit = nullptr;
QLineEdit* fromLineEdit = nullptr;
QLineEdit* subjectLineEdit = nullptr;
QTextEdit* messageTextEdit = nullptr;
};
#endif // MAINWINDOW_HPP
main.cpp
#include "Mailer.hpp"
#include <QApplication>
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
Mailer mailer;
return a.exec();
}

C++, Qt Signals & slots

I'm trying to understand Qt 4.8 signals and slots so I wrote some code to test it out for myself. Eventually, I want to be able to use a common source file in my project so that serial ports can be accessed from any source file in the project.
I set up a Qt GUI application and added a C++ class header and source file, shown below.
When I try to build, I get the error message when I try to emit the signal.
/home/user/QTProjects/stest1/stest1/ser.cpp:25: error: invalid use of 'this' in non-member function
I haven't even gotten to the stage of setting up the connections yet!
My newbie status is obvious, I'd be grateful for any help.
Thanks,
James
The following is the MainWindow.cpp:-
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ser.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ser *j = new ser;
j->init();
connect (this, SIGNAL(click()), ser, SLOT(testprint()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QByteArray ba1;
ba1.resize(6);
ba1[0]='H'; ba1[1]='e'; ba1[2]='l'; ba1[3]='l'; ba1[4]='o'; ba1[5]='\n';
this->printtext(ba1);
}
void MainWindow::printtext(const QByteArray &data)
{
ui->textEdit->insertPlainText(QString(data));
}
The following is the MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void printtext(const QByteArray &data);
private:
Ui::MainWindow *ui;
signals:
// void click;
};
#endif // MAINWINDOW_H
The following is ser.cpp:-
#include "ser.h"
#include <QObject>
ser::ser(QObject *parent) :
QObject(parent)
{
}
void ser::init()
{
// connect(this->, SIGNAL(testsignal), MainWindow, SLOT(printtext(const QByteArray &data)));
}
void ser::testprint()
{
QByteArray ba1;
ba1.resize(8);
ba1[0]='S'; ba1[1]= '0'; ba1[2]= ' '; ba1[3]= 'l'; ba1[4]='o'; ba1[5]='n'; ba1[6]='g'; ba1[7]='\n';
emit this->testsignal(ba1);
}
The following is ser.h
#ifndef SER_H
#define SER_H
#include "mainwindow.h"
#include <QObject>
class ser : public QObject
{
Q_OBJECT
public:
explicit ser(QObject *parent = 0);
void init();
signals:
void testsignal(const QByteArray &data);
private slots:
void testprint();
public slots:
};
#endif // SER_H
Your method is implemented as void testprint() { ... }, but it should be void ser::testprint() { ... }. It's in your cpp file.
Also note that you don't need to use this-> to refer to class members. emit testsignal(ba1); will fork fine.
I think should be
connect (this, SIGNAL(click()), j, SLOT(testprint()));
instead of
connect (this, SIGNAL(click()), ser, SLOT(testprint()));
that apart, I can't spot where you connect testsignal
Great, that worked.
connect (this, SIGNAL(click()), j, SLOT(testprint()));
My next problem is connecting the signal in ser to the slot in the MainWindow. I used
connect(j,
SIGNAL(testsignal),
this,
SLOT(printtext(const QByteArray &data)));
It was inserted immediately after the other connect statement.
This does not print out the expected message "Slong". It also does not give me any error! What is the problem?
James