Cannot execute a slot which should change GUI in Qt - c++

I am trying to implement signal/slot connection which will show alert in editLine. I have no idea why the slot is not executing.
I tried: connect(mKlient, SIGNAL(showInfo(QString)), qApp, SLOT(aboutQt()));
To be sure that the signal is working correctly. So I think that something is wrong with the slots. Below is the code:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <klient.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Klient *mKlient;
private:
Ui::MainWindow *ui;
public slots:
void onShowInfo(QString);
private slots:
//void on_pushButton_clicked();
void on_pushButtonConnect_clicked();
};
#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);
onShowInfo("This alert is working"); // works
//-------------------Here is the signal/slot connection-------------------------------------
mKlient = new Klient(this);
connect(mKlient,SIGNAL(showInfo(QString)),this, SLOT(onShowInfo(QString))); //not working - no idea why :/
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onShowInfo(QString text){
ui->lineEdit->setText(text);
}
void MainWindow::on_pushButtonConnect_clicked()
{
if(ui->radioButtonTCP->isChecked()){
mKlient->disconnect(this);
mKlient->connectToServer(ui->lineEditIpAddress->text(), ui->lineEditTcpPort->text().toInt());
}
}
klient.h
#ifndef KLIENT_H
#define KLIENT_H
#include <QObject>
#include <QTcpSocket>
#include <QAbstractSocket>
class Klient : public QObject
{
Q_OBJECT
public:
explicit Klient(QObject *parent = 0);
void connectToServer(QString,int);
bool isConnectedFlag;
signals:
void showInfo(QString);
public slots:
void connected();
private:
QTcpSocket *mSocket;
};
#endif // KLIENT_H
klient.cpp
#include "klient.h"
Klient::Klient(QObject *parent) :
QObject(parent)
{
isConnectedFlag = false;
}
void Klient::connectToServer(QString address, int port){
mSocket = new QTcpSocket(this);
connect(mSocket, SIGNAL(connected()),this,SLOT(connected()));
mSocket->connectToHost(address,port);
if(!mSocket->waitForConnected(1000)){
//error mSocket->errorString();
}
}
void Klient::connected(){
emit showInfo("Connected"); //this information should be on lineEdit
mSocket->write("siemanko"); //executing properly
isConnectedFlag = true;
}
}
I was following this tutorial to find a bug, but no results:
https://samdutton.wordpress.com/2008/10/03/debugging-signals-and-slots-in-qt/
Am I doing something wrong? I am new to Qt so maybe accessing to the GUI is more complicated than I thought.

I found the answer...
In
void MainWindow::on_pushButtonConnect_clicked()
{
if(ui->radioButtonTCP->isChecked()){
mKlient->disconnect(this);
mKlient->connectToServer(ui->lineEditIpAddress->text(), ui->lineEditTcpPort->text().toInt());
}
}
I thought that I am disconnecting TCP connection. Unfortunatelly I was disconnecting signal/slot connection.
Should I delete my question ? How to do this ?

Related

Qthreading and signal emiting from it

doit is a Qthread subclass with a signal kif() but the signal emitting is not working I want to show the resualt of gav() on one of my editLines at the same time as its changes inside gav() pls help :((((((( I wasted so much time to find out how I can do it :((((((
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
doit.h
#ifndef DOIT_H
#define DOIT_H
#include <QThread>
class doit : public QThread
{
Q_OBJECT
public:
doit();
int i;
QString z;
void run() ;
void gav(int &i);
signals:
void kif(const QString &text);
};
#endif // DOIT_H
#include "doit.h"
doit::doit()
{
}
void doit::run()
{
gav(i);
}
void doit::gav(int &i)
{
int k=i;
for (int b=0;b<k;b++){
i=b;
z= QString::number(i);
emit kif(z);
}
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "doit.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
doit *dovit=new doit;
private slots:
void checkInput(const QString &text);
private:
Ui::MainWindow *ui;
};
#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);
//QObject::connect(dovit,doit::kif(&QString),this , MainWindow::checkInput(QString)))
connect(dovit,SIGNAL(kif(QString)),this,SLOT(checkInput(QString)));
dovit->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::checkInput(const QString &text)
{
ui->lineEdit_3->setText(text);
}
and Im new in this , so pls tell me exactlly where should I change or add and what tanx alot
Well it finally worked after wasting a lot of my time. For anyone wondering vtables was the problem (as I read its a bug (not sure)) and I should just
right click on the project folder and rebuild and run qmake the project ,
I added Qobject.h too and it worked.
working code:
(it is also a simple and good example of meta signaling in qt if you need it)
doit.h
#define DOIT_H
#include <QThread>
#include <QObject>
class doit : public QThread
{
Q_OBJECT
public:
doit();
void gav();
void run() ;
signals:
void kif(QString text);
};
#endif // DOIT_H
doit.cpp
#include "doit.h"
#include <QDebug>
doit::doit()
{
}
void doit::run()
{
gav();
}
void doit::gav()
{
QString z;
for (int i=0;i<11;i++){
z="mamad";
z = z + QString::number(i);
QThread::sleep(1);
qDebug()<<z;
emit kif(z);
}
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "doit.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
doit *dovit=new doit;
//doit dovit;
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#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);
connect(dovit,SIGNAL(kif(QString)),this->ui->lineEdit_3,SLOT(setText(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
dovit->start();
}

Qt - Right Way to Implement Custom Signals and Slots

I have one MainWindow and one Class; I want to send data between them using custom signal and slot. I can't seem to figure it out, I need help.
Here is my code:
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <iostream>
#include "receive.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
signals:
void sendit(QString name);
private slots:
void on_send_button_clicked();
void display(QString e)
{
std::cout<<"Here is where I am called this "<<e.toStdString()<<std::endl;
}
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "receive.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
Receive *r = new Receive();
connect(this, SIGNAL(sendit(QString)), r, SLOT(display(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_send_button_clicked()
{
emit sendit(ui->lineEdit->text());
}
receive.h
#ifndef RECEIVE_H
#define RECEIVE_H
#include <iostream>
#include <QDialog>
class Receive : public QDialog
{
public:
Receive();
private slots:
void display(QString e);
};
#endif // RECEIVE_H
receive.cpp
#include "receive.h"
#include "mainwindow.h"
Receive::Receive()
{
}
void Receive::display(QString e)
{
std::cout<<"Here is where I am called this "<<e.toStdString()<<std::endl;
}
When I run this program, I get this message:
06:26:29: Starting C:\Users\Troy\Documents\build-tests-Desktop_Qt_5_14_1_MinGW_32_bit-Debug\tests.exe ...
QObject::connect: No such slot QDialog::display(QString) in ..\tests\mainwindow.cpp:11
QObject::connect: (sender name: 'MainWindow')
How do I get this done, please?
Thank you for your help.
Your slot in Receive needs to be public not private. Much the same as other class members, private slots can only be used by the class itself.
If you use the modern connect syntax you'll get a better compile time error:
connect(this, &MainWindow::sendit, r, &Receive::display);
You also need to make sure you add Q_OBJECT to every Qt class, it is missing from Receive.

Example SLOT/SIGNAL between two object QT

My app, consists in 2 different object (QObject and QMainWIndow), and I am wondering how to communicate between them with SLOT/SIGNAL. Moreover, does existing better approach ?
Can someone make an simple example ? Thank :)
sample
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "ui_mainwindow.h"
#include "object.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "object.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->chkState, SIGNAL(clicked()), this, SLOT(object->chkState();));
}
MainWindow::~MainWindow()
{
delete ui;
}
object.h
#ifndef OBJET_H
#define OBJET_H
#include "mainwindow.h"
#include <QMainWindow>
#include <QObject>
class Object : public QObject
{
Q_OBJECT
public:
explicit Object(QObject *parent = 0);
bool state;
signals:
private slots:
void chkState(Ui::MainWindow *ui);
};
#endif // OBJET_H
objet.cpp
#include "object.h"
#include "mainwindow.h"
Object::Object(QObject *parent) : QObject(parent)
{
}
void Object::chkState(Ui::MainWindow *ui)
{
if (ui->chkState->isChecked())
{
ui->state->setText("true");
state = true;
}
else
{
ui->state->setText("false");
state = false;
}
}
Here is a simple example of how to emit signals and slots.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "object.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void transmit_to_object(bool value);
private slots:
void receive_from_object(bool value);
void on_checkBox_clicked();
private:
Ui::MainWindow *ui;
object m_object;
};
#endif // MAINWINDOW_H
#ifndef OBJECT_H
#define OBJECT_H
#include <QObject>
class object : public QObject
{
Q_OBJECT
public:
explicit object(QObject * parent = 0);
signals:
void transmit_to_gui(bool value);
private slots:
void receive_from_gui(bool value);
private:
bool state;
};
#endif // OBJECT_H
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(&m_object,SIGNAL(transmit_to_gui(bool)),this,SLOT(receive_from_object(bool)));
connect(this,SIGNAL(transmit_to_object(bool)),&m_object,SLOT(receive_from_gui(bool)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::receive_from_object(bool value)
{
if(value)
{
ui->lineEdit->setText("true");
}
else
{
ui->lineEdit->setText("false");
}
}
void MainWindow::on_checkBox_clicked()
{
if(ui->checkBox->isChecked())
{
emit transmit_to_object(true);
}
else
{
emit transmit_to_object(false);
}
}
#include "object.h"
#include "mainwindow.h"
object::object(QObject *parent)
{
}
void object::receive_from_gui(bool value)
{
state = value;
emit transmit_to_gui(state);
}
There are several errors in your code.
First:
connect(ui->chkState, SIGNAL(clicked()), this, SLOT(object->chkState();));
Here you say:
"when we click on the ui->chkState, I want you call a function in this, which is the object->chkState slot". That's definitly not what you want.
What is object ? this object hasn't been created. What you want is :
connect(ui->chkState, SIGNAL(clicked()), myobject, SLOT(chkState()));
with myobject an object of type Object so you need to add in your mainwindow.h a
Object *myobject;
and in your mainwindow.cpp before the connect:
myobject = new Object(this);
Moreover, your function void chkState(Ui::MainWindow *ui); won't work because you cannot get the mainwindow ui in parameter like that.
What I advise you to do, if it's only for tests so you know that parent is the type of MainWindow, you can do:
void Object::chkState()
{
MainWindow* parent = static_cast<MainWindow*>(parent());
if (parent->ui->chkState->isChecked())
{
parent->ui->state->setText("true");
state = true;
}
else
{
parent->ui->state->setText("false");
state = false;
}
}
So the parameter in your slot is removed.

Qt slot method (which is another class) not firing when emiting the signal

I know this question asked many times but still confused and cannot find a solution.
I have a MainWindow and a class.
In my class I have a signal which I emit in the method call.
Problem: Slot method is not firing.
Here is my code.
BWorker.h
#pragma once
#include <QObject>
class BWorker : public QObject
{
Q_OBJECT
public:
BWorker(QObject *parent);
~BWorker();
void doSomething();
signals:
void signalSomething();
};
BWorker.cpp
#include "BWorker.h"
BWorker::BWorker(QObject *parent)
: QObject(parent)
{
}
BWorker::~BWorker()
{
}
void BWorker::doSomething()
{
emit signalSomething();
}
QtGuiApplication1.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtGuiApplication1.h"
class QtGuiApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtGuiApplication1(QWidget *parent = Q_NULLPTR);
public slots:
void workDone();
private:
Ui::QtGuiApplication1Class ui;
};
QtGuiApplication1.cpp
#include "QtGuiApplication1.h"
#include "BWorker.h"
QtGuiApplication1::QtGuiApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
BWorker bworker(this);
connect(&bworker, SIGNAL(bworker.signalSomething), this, SLOT(workDone()));
bworker.doSomething();
}
void QtGuiApplication1::workDone() {
}
Your problem is here:
SIGNAL(bworker.signalSomething)
This is not valid and you should see a message in terminal saying that there is no such signal. The correct syntax for your case would be:
SIGNAL(signalSomething())
Please post your code by copy-pasting it. Do not edit the code: The problem could be emerged from where you edited.
The code of mine worked fine.
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();
public slots:
void workDone();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "worker.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
Worker worker(this);
connect(&worker, SIGNAL(signalSomething()), this, SLOT(workDone()));
//connect(&worker, &Worker::signalSomething, this, &MainWindow::workDone);
worker.doSomething();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::workDone()
{
qDebug() << "Done.";
}
worker.h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
void doSomething();
signals:
void signalSomething();
public slots:
};
#endif // WORKER_H
worker.cpp:
#include "worker.h"
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::doSomething()
{
emit signalSomething();
}
Application Output:
Debugging starts
Done.
Debugging has finished
Printed out "Done." means the codes are working.

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