Slots and signals in QThread - c++

I'm tryng to connect() a signal in thread 2 to slot in a main thread, I have constructor like that, which runs in thread 2 as a child class of QThread:
InputHandler::InputHandler()
{
connect(this, SIGNAL(write(User*, Message)), TTCServer::ttcserver, SLOT(write(User*, Message)));
qDebug() << "new thread created!";
}
but I get an runtime error
QObject::connect: No such signal QThread::write(User*, Message)
My inputhandler.h looks like that:
#ifndef INPUTHANDLER_H
#define INPUTHANDLER_H
#include <QThread>
#include <QDebug>
#include <QString>
#include "message.h"
#include "data.h"
class InputHandler : public QThread
{
public:
InputHandler();
void run();
private:
Message message;
void login(User* user, QString login);
void sendLogins(User* user);
void startGameWith(User* user, QString opponentLogin);
signals:
void write(User* user, Message message);
};
#endif // INPUTHANDLER_H
And If it does matter, I'm also inncluding ttcserver.h:
#ifndef TTCSERVER_H
#define TTCSERVER_H
#include <QTcpServer>
#include <QObject>
#include <QDebug>
#include "data.h"
#include "user.h"
#include "message.h"
#include "inputhandler.h"
class TTCServer : public QTcpServer
{
Q_OBJECT
public:
explicit TTCServer();
static TTCServer* ttcserver;
void run();
signals:
public slots:
void newConnection();
void write(User* user, Message message);
private:
QTcpServer* server;
Message* message;
void handleInputFrom(User* user);
};
#endif
// TTCSERVER_H
void write method is definied in ttcserver.cpp like that:
void TTCServer::write(User* user, Message message)
{
qDebug() << "Signal recieved!";
}
So why write(User*, Message) in a connect() function tries to be QThread::write() instead of InputHandler::write()?
User and Message are classes, to be clear.

You forgot to add the Q_OBJECT macro into InputHandler:
class InputHandler : public QThread
{
Q_OBJECT
public:
InputHandler();
void run();
<...>
Since the macro is missing, moc will not create the corresponding code for signals/slots to work in that class, thus it tries to connect to QObject, since it does have the macro, and is the base class.

Related

can't emit a signal from a QThread that is inside of QThread in QT(GUI)

/////////// this is the parent thread class
//// serverstartThread.h
#ifndef SERVERSTARTTHREAD_H
#define SERVERSTARTTHREAD_H
#include <QObject>
#include <QDebug>
#include "QThread"
#include "listenerthread.h"
class ServerStart : public QObject
{
Q_OBJECT
signals:
void newClientConnectedSig();
public:
explicit ServerStart(QObject *parent = nullptr);
~ServerStart();
listenerThread* listenerthread;
QThread* thread;
public slots:
void run();
void newClientConnectedSig2();
};
#endif // SERVERSTARTTHREAD_H
//// serverstartThread.cpp
#include "serverstartThread.h"
ServerStart::ServerStart(QObject *parent) : QObject(parent)
{
}
ServerStart::~ServerStart(){
}
void ServerStart::newClientConnectedSig2(){
qInfo() << "helooooooooooooooooo";//this doesn't run
emit newClientConnectedSig();
}
void ServerStart::run()
{
qInfo() << "\nthread is running\n";
//ListenForNewConnection
listenerthread = new listenerThread();
thread = new QThread(this);
listenerthread->moveToThread(thread);
QObject::connect(thread, &QThread::started, listenerthread, &listenerThread::run);
QObject::connect(listenerthread, &listenerThread::newClientConnectedSig, this, &ServerStart::newClientConnectedSig2);
thread->start();
//functionthathasinfiniteloop();
this->deleteLater();
}
/////////// this is the child thread class
//// listenerThread.h
#ifndef LISTENERTHREAD_H
#define LISTENERTHREAD_H
#include <QObject>
#include <QDebug>
#include <QThread>
#include "clienthandlerThread.h"
class listenerThread : public QObject
{
Q_OBJECT
public:
explicit listenerThread(QObject *parent = nullptr);
~listenerThread();
void run();
clientHandlerThread* clienthandlerthread;
QThread* thread;
public slots:
signals:
void newClientConnectedSig();
};
#endif // LISTENERTHREAD_H
//// listenerThread.cpp
#include "listenerthread.h"
listenerThread::listenerThread(QObject *parent) : QObject(parent)
{
}
listenerThread::~listenerThread()
{
}
void listenerThread::run(){
//does somthing here
emit newClientConnectedSig();
//does something here
}
1)inside my parent thread class serverstart.cpp i run a thread that runs the second class listenerthread.cpp (child thread).
2)inside the child thread class listenerthread.cpp i emit a signal.
3)inside serverstart.cpp i connect the signal, but QObject::connect() in the parent thread serverstart.cpp never receives the signal from the child thread listenerthread.cpp.
what i've tried
instead of running listenerthread.cpp in a thread, i made a pointer of it(listenerThread listenerthread = new listenerThread();). then listenerThread->run(); called the run method which emits a signal. and works.
which means
can't emit a signal from a child thread to the parent thread.
i really hope this is enough to be fully understood.
is this because of the Thread inside of a thread?

Signals and slots with std::vector : lvalue issue

In one of my project, I am trying to use the Qt signals and slots mechanism with a std::vector<bool> as parameter. My project is equivalent to the following minimal code :
class App
// app.h
#ifndef APP_H
#define APP_H
#include <QObject>
#include <QSharedPointer>
#include "emitter.h"
#include "receiver.h"
class App : public QObject
{
Q_OBJECT
public:
App(QObject *parent = 0);
};
#endif // APP_H
// app.cpp
#include "app.h"
App::App(QObject* parent): QObject(parent)
{
Emitter emitter;
Receiver receiver;
receiver.attachEmitter(emitter);
emitter.run();
}
class Emitter
//emitter.h
#ifndef EMITTER_H
#define EMITTER_H
#include <QObject>
#include <vector>
#include "helper.h"
class Helper;
class Emitter : public QObject
{
Q_OBJECT
public:
explicit Emitter(QObject *parent = 0);
void run();
signals:
void triggered(std::vector<bool> value);
};
#endif // EMITTER_H
// emitter.cpp
#include "emitter.h"
Emitter::Emitter(QObject *parent) : QObject(parent)
{
}
void Emitter::run()
{
emit triggered(Helper::value());
}
class Receiver
//receiver.h
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QObject>
#include <QDebug>
#include <QSharedPointer>
#include "emitter.h"
class Emitter;
class Receiver : public QObject
{
Q_OBJECT
public:
explicit Receiver(QObject *parent = 0);
void attachEmitter(QSharedPointer<Emitter> emitter);
signals:
public slots:
};
//receiver.cpp
#include "receiver.h"
Receiver::Receiver(QObject *parent) : QObject(parent)
{
}
void Receiver::attachEmitter(QSharedPointer<Emitter> emitter)
{
connect(emitter.data(), &Emitter::triggered, [this](std::vector<bool> value) {
qDebug() << "Received value";
});
}
For some reason, the compiler doesn't like it at all and prints me this stack :
What do I have to do ? Thank you
Signal/slot values passend by value have to be registered with the Qt meta system and I don't think the std::vector is registered by default. Is there a reason you're not using QVectorinstead?
For futher information look at Q_DECLARE_METATYPE and qRegisterMetaType().

c++ Is it possible to inherit a class, but not what that class inherits? (qt)

I have four classes at the moment. Client, ChatWindow, FunctionCall and MainWindow. What I ultimatly would want to do is not have FunctionCall class and have a virtual inheritance of Client in ChatWindow and MainWindow, but QT, or more specifically QObject doesn't allow this.
The reason I thought a virtual class would be good is to not create two different instances of a class, but rather have ChatWindow and MainWindow share the variables.
I've made a FunctionCall class that inherits Client, and I've created virtual inheritance between ChatWindow and MainWindow with FunctionCall
ChatWindow.h
#ifndef CHATWINDOW_H
#define CHATWINDOW_H
#include <QWidget>
#include "functioncall.h"
namespace Ui {
class ChatWindow;
}
class ChatWindow : public QMainWindow, public virtual FunctionCall
{
Q_OBJECT
public:
explicit ChatWindow(QWidget *parent = 0);
~ChatWindow();
private slots:
void on_sendButton_clicked();
private:
Ui::ChatWindow *ui;
};
#endif // CHATWINDOW_H
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "functioncall.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow, public virtual FunctionCall
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_connectButton_clicked();
private:
Ui::MainWindow *ui;
protected:
void something();
};
#endif // MAINWINDOW_H
FunctionCall.h
#ifndef FUNCTIONCALL_H
#define FUNCTIONCALL_H
#include "client.h"
class FunctionCall : public Client
{
public:
FunctionCall();
};
#endif // FUNCTIONCALL_H
Client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <QApplication>
#include <QWidget>
#include <QDialog>
#include <QObject>
#include <QLabel>
#include <QComboBox>
#include <QLineEdit>
#include <QPushButton>
#include <QDialogButtonBox>
#include <QTcpSocket>
#include <QString>
#include <QTcpServer>
#include <QStringList>
#include <QNetworkSession>
#include <QDataStream>
#include <QGridLayout>
#include <QMainWindow>
class Client : public QDialog
{
Q_OBJECT
public:
Client(QWidget *parent = 0);
public slots:
void read();
void displayError(QAbstractSocket::SocketError socketError);
void sessionOpened();
void connectedSocket();
void disconnectedSocket();
void pushToSocket(
quint8 registerForm,
QString registerUsername,
QString registerPassword,
QString username,
QString text
);
QString readFromSocket();
void saveToFile(std::string fileName, QString text);
public:
QTcpSocket *tcpSocket;
quint16 blockSize;
QNetworkSession *networkSession;
QTcpServer *tcpServer;
struct HeaderFile {
quint8 registerForm = 2;
QString registerUsername;
QString registerPassword;
QString username;
QString text;
};
public:
QStringList *hostCombo;
void send(QString username, QString text);
void loginRegisterConnect(QString host, int port, QString username, QString password);
friend QDataStream & operator<<(QDataStream& str, const HeaderFile & data) {
str << data.registerForm << data.registerUsername << data.registerPassword << data.username << data.text;
return str;
}
friend QDataStream & operator>>(QDataStream& str, HeaderFile & data) {
str >> data.registerForm >> data.registerUsername >> data.registerPassword >> data.username >> data.text;
return str;
}
};
#endif // CLIENT_H
Problem is I'm getting an error, probably because the Client class inherits QDialog.
I was wondering if it was possible only to inherit from Client, and not what Client also inherits, basically I want to use the functions in the Client class. But nothing it inherits from QDialog.
It doesn't compile here is the error:
C:\\main.cpp:9: error: C2385: ambiguous access of 'show'
could be the 'show' in base 'QWidget'
or could be the 'show' in base 'QWidget'
Solved my issue:
I basically made a singleton of the Client class, and created instances of that.
No, because that would violate the type equivalency (Liskov Substitution Principle). Basically it means that since you inherit from Client every FunctionCall object will also be a Client object and since every Client object has to be a QDialog object it follows that the FunctionCall object has to be a QDialog object.
Also what you've seem to be victim of here is that you use multiple inheritance and the same (non-virtual) base appears twice in the inheritance tree. You probably should think twice or thrice about this: is this really the right design? is this really what you want? Note that the different occations of QWidget in the inheritance tree are different (sub) objects.

Qt Error - error: Not a signal or slot declaration

I'm attempting to multi-thread server in QT. However, I keep getting this annoying error:
error: Not a signal or slot declaration (Line 21)
Here is my code:
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QTcpSocket>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(int ID, QObject *parent = 0);
void run();
signals:
void error(QTcpSocket::SocketError socketerror);
public slots:
void readyRead();
void disconnected();
public slots:
QTcpSocket *socket;
int socketDescriptor; //Socket ID Number
};
#endif // MYTHREAD_H
The error message tells you exactly what the problem is. You declare member variables as being slots, but they are not. I would change your class as follows:
class MyThread : public QThread
{
Q_OBJECT
[..]
private: // or public:
QTcpSocket *socket;
int socketDescriptor;
};

circular dependency QThread

I have a task to create a chess game with support for network play.
For development I've been using Qt.
The problem is as follows:
I have class "MyServer":
Header file->
//Header file "MyServer.h"
#ifndef MYSERVER_H
#define MYSERVER_H
#include <QTcpServer>
#include <QTcpSocket>
#include <mythread.h>
#include <QDebug>
class MyServer : public QTcpServer
{
Q_OBJECT
public:
explicit MyServer(QObject *parent = 0);
void startServer();
QList<QString> *usersOnline;
QList<QTcpSocket*> *connections;
signals:
public slots:
protected:
void incomingConnection(int socketDescriptor);
private:
QTcpServer* server;
//QTcpSocket* socket;
//QByteArray* bytes;
//QString* str;
};
#endif // MYSERVER_H
cpp.file
#include "myserver.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::startServer()
{
this->listen(QHostAddress::Any,1234);
usersOnline=new QList<QString>;
}
void MyServer::incomingConnection(int socketDescriptor)
{
MyThread* thread=new MyThread(socketDescriptor,this,this);
thread->run();
}
As you can see, this class with a new connection creates a new thread.
Class "MyThread".
Header file
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QTcpSocket>
#include <QTcpServer>
#include <QDebug>
#include <QDataStream>
#include <QObject>
#include <myserver.h>
class MyServer;
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(int ID,MyServer* s,QObject *parent = 0);
void run();
signals:
public slots:
void readyRead();
private:
QTcpSocket* socket;
int socketDescriptor;
};
#endif // MYTHREAD_H
cpp.file
#include "mythread.h"
MyThread::MyThread(int ID,MyServer* s,QObject *parent) :
QThread(parent)
{
//this->mainserver=parent;
//parent=new MyServer();
//qDebug()<<s->usersOnline;
this->socketDescriptor=ID;
}
void MyThread::run()
{
qDebug()<<"Starts thread";
socket=new QTcpSocket();
socket->setSocketDescriptor(this->socketDescriptor);
connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::DirectConnection);
exec();
}
void MyThread::readyRead()
{
QDataStream in(this->socket);
quint32 n;
in>>n;
qDebug()<<n;
QByteArray bytes;
QDataStream out(&bytes,QIODevice::WriteOnly);;
QString str;
switch (n) {
case 1:
in>>str;
qDebug()<<str;
//usersOnline->append(str);
//qDebug()<<*(usersOnline);
//out(&bytes,QIODevice::WriteOnly);
//out<<(*usersOnline);
//for(int i=0;i<this->connections->length();i++)
//{
//connections->at(i)->is
//connections->at(i)->write(bytes);
//connections->at(i)->waitForBytesWritten(2000);
// }
break;
case 2:
in>>str;
qDebug()<<str;
break;
}
}
In "MyThread" constructor i pass pointer to "MyServer" class to use the fields "usersOnline","connections" and "MyServer" method.
Thus, i have in my architecture "circular dependency" with "MyServer" and "MyThread" class.
How to change architecture?
Thanks a lot.
Remove #include <myserver.h> from your thread header. You already have class MyServer; forward definition there, it will be enough.