Qt - Right Way to Implement Custom Signals and Slots - c++

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.

Related

Qt Change label text from another class

i'm trying to change the label text of Class A via Class B using Qt but i can't get it working, here's my codes:
Class A:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "loldata.h"
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
LoLData *lold = new LoLData();
QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(updateData()));
QObject::connect(lold, SIGNAL(updatePlayerID(QString)), ui->label, SLOT(setText(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::updateData()
{
LoLData summoner;
summoner.getSummonerData("Snylerr");
}
Class A: (.h)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <string>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void updateData();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Class B:
#include "loldata.h"
#include "mainwindow.h"
using namespace std;
int LoLData::getSummonerData(QString playerName)
{
emit updatePlayerID("playerName");
return 0;
}
Class B: (.h)
#ifndef DEF_LOLDATA
#define DEF_LOLDATA
#include <QApplication>
#include <QObject>
#include <string>
class LoLData : public QObject
{
Q_OBJECT
public:
int getSummonerData(QString playerName);
signals:
void updatePlayerID(QString playerName);
private:
};
#endif
You can see that i tried to use slots and signals but the text of the label is not changing, i saw a lot of examples on internet but i can't get them working
Thanks for your reply.
You are creating a new instance of LoLData here:
void MainWindow::updateData()
{
LoLData summoner;
summoner.getSummonerData("Snylerr");
}
This instance of LoLData named summoner is not connected to your label's setText slot.
LoLData *lold = new LoLData(); - this instance of LolData is connected to you label's setText slot.
What should yo do?
It depends on what you want to accomplish:
either connect your summoner instance to the label by inserting a QObject::connect(&summoner...) inside yourupdateData` method;
or you don't instantiate a new LolData variable and use lold inside your updateData function:
void MainWindow::updateData()
{
lold->getSummonerData("Snylerr");
}
Also in this case you have to put lold as a member variable.
In your MainWindow constructor, you connect your lold object to the setText slot.
But in updateData, you use an other object (summoner) which is not connect to anything. So when you use getSummonerData on summoner, the signal updatePlayerID is emitted nut they is no slot connected to it.

Set connect from another class in QT

I don't get it.
loginview.h
#ifndef LOGINVIEW_H
#define LOGINVIEW_H
#include <QMainWindow>
#include <QDebug>
#include <QPushButton>
class LoginView : public QWidget
{
public:
QWidget *LoginViewSetup(QWidget * wdgMain);
public slots:
virtual void LogInUser();
virtual void CreateUser();
public:
QPushButton *logInBtn;
QPushButton *createBtn;
};
#endif // LOGINVIEW_H
loginview.cpp
#include "loginview.h"
QWidget *LoginView::LoginViewSetup(QWidget * wdgMain)
{
//some code
return wdgCenter;
}
void LoginView::LogInUser()
{
//some code
}
void LoginView::CreateUser()
{
//some code
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <loginview.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QWidget * wdgMain;
};
#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);
wdgMain = new QWidget(this);
LoginView LoginViewObj;
QWidget *wdgCenter = LoginViewObj.LoginViewSetup(wdgMain);
setCentralWidget( wdgMain );
connect(LoginViewObj.createBtn, SIGNAL (released()), &LoginViewObj, SLOT (CreateUser()));
}
MainWindow::~MainWindow()
{
delete ui;
}
Problem:
QObject::connect: No such slot QWidget::CreateUser() in
../proj/mainwindow.cpp:16
I tried to add Q_OBJECT to the loginview.h and then rebuild project with QMAKE. After that there is no warning about slot, but buttons still not active. Program don't jump to handle of the button in debug mode.
Please, help me to understand what's wrong? I have an object of another class LoginView and I pass this object as a reciever for a slot. Why it passes through my class and searches slot in QWidget?

Cannot execute a slot which should change GUI in Qt

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 ?

QT signal-slot not received

I am trying to connect a signal from a second QMainWindow to the mainwindow. It doesn't say anything about a problem connection when the program is launched, but It doesn't work. I am not very familiar with C++ and Qt so maybe is something simple.
My code consists on a Mainwindow used as a SCADA with Start, stop, On, off buttons. In the second qmainwindow I created a terminal where you can type, start,stop... There, I would like to emit a signal to my MainWindow which is in charge of controlling the multiple threads and windows. The problem is that I cannot connect to my slot. I present here a simple overview of this two pieces of code.
Terminal. h
#ifndef TERMINAL__H
#define TERMINAL__H
#include <QMainWindow>
#include <QTextEdit>
#include <QLineEdit>
#include <QObject>
namespace Ui {
class Terminal_;
}
class Terminal_ : public QMainWindow
{
Q_OBJECT
public:
explicit Terminal_(QWidget *parent = 0);
~Terminal_();
signals:
void turnonPLC_terminal();
public slots:
void newline();
private:
Ui::Terminal_ *ui;
QTextEdit* mTerminal;
QLineEdit* mInput;
};
#endif // TERMINAL__H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "terminal_.h"
#include "terminal_help.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Terminal_ *terminal;
public slots:
void turnon_terminal();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "terminal_.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
terminal = new Terminal_(this);
connect(terminal, SIGNAL(turnonPLC_terminal()), this, SLOT(turnon_terminal()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::turnon_terminal(){
turnonPLC=1;
}
terminal_.cpp
#include "terminal_.h"
#include "ui_terminal_.h"
#include <QDockWidget>
#include <QWidget>
#include <QLineEdit>
QString on=("on");
Terminal_::Terminal_(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Terminal_)
{
ui->setupUi(this);
mTerminal = new QTextEdit();
setCentralWidget(mTerminal);
mInput = new QLineEdit();
QDockWidget* qdw = new QDockWidget;
qdw->setWidget(mInput);
addDockWidget(Qt::BottomDockWidgetArea, qdw);
connect (mInput, SIGNAL(returnPressed()),
this, SLOT(newline()));
}
Terminal_::~Terminal_()
{
delete ui;
}
void Terminal_::newline(){
QString command = mInput->text();
if (command==on){
emit turnonPLC_terminal();
}
}
Thanks
The signal-slots part in the code works perfectly. (compiled and tested with some small modifications)
After entering "on" (not On as written in question)
Terminal_::newline() slot called, turnonPLC_terminal() is fired and finally
void MainWindow::turnon_terminal() is called.
However, there are some small details the header file is called terminal_.h, not Terminal.h turnonPLC is not defined. terminal is created by not displayed (no show-call).
I guess, there are simply some many small logic errors. Try to use debugger or trace the chain of expected calls with qDebug.

write on ui label from different class in qt

I am using Qt in my project and facing some difficulty in accessing ui label from other class,I have mainwindow and Yar class as shown below.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "yar.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Yar b;
private:
Ui::MainWindow *ui;
public slots:
void dispal();
private slots:
void on_pushButton_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);
QObject::connect(ui->pushButton,SIGNAL(clicked()),&b,SLOT(lll()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::dispal(){
ui->label->setText("hello");
}
Yar.h
#ifndef YAR_H
#define YAR_H
#include <QObject>
class Yar : public QObject
{
Q_OBJECT
public:
explicit Yar(QObject *parent = 0);
public slots:
void lll();
};
#endif // YAR_H
void MainWindow::on_pushButton_clicked()
{//ui->label->setText("hello");
//b.wrrrot();
//dispal();
}
Yar.cpp
#include "yar.h"
#include <iostream>
Yar::Yar(QObject *parent) :
QObject(parent)
{
//setupUi(this);
//QObject::connect(&a, SIGNAL(dis), &a, SLOT(dispal()));
//emit wrrrot();
}
void Yar::lll(){
//emit wrrrot();
std::cout<<"gfggdf"<<std::endl;
}
In my gui i have one push button and one label, I have connected push button with lll() function of class Yar and when I click push button it is displaying gfggdf in console but I want to display this text in ui label, could you please help me how can I display my data in ui label from function lll();
One possible solution is to emit signal from Yar::lll() i.e.
emit updateLabelText("your text");
And connect this signal to the slot that handles GUI (changes label with given text) in the MainWindow.