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;
};
Related
/////////// 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?
I want to call a function when a button click. the implementation of the button is in the abstract class. but when I compile I'm getting this error.
This is my .h file of the base class
#ifndef HOME_H
#define HOME_H
#include<QGraphicsScene>
#include <QGraphicsScene>
#include<QPushButton>
class home
{
Q_OBJECT
public:
home();
virtual void set_home_background()=0 ;
QGraphicsScene *scene3;
QPushButton *button3;
private slots:
virtual void startgame1();
};
#endif // HOME_H
This is the base class
#include "home.h"
#include<QGraphicsScene>
#include<QGraphicsProxyWidget>
#include "QMessageBox"
home::home()
{
}
void home::set_home_background()
{
button3 = new QPushButton;
QObject::connect(button3,SIGNAL(clicked()),this,SLOT(startgame1()));
QGraphicsProxyWidget *proxy = this->scene3->addWidget(button3);
button3->setAutoFillBackground(true);
button3->setIcon(QIcon(":/Images/ng.png"));
button3->setIconSize(QSize(131,41));
proxy->setPos(130,430);
scene3->addItem(proxy);
}
void home::startgame1()
{
QMessageBox q;
q.setText("");
q.exec();
}
I'm getting this error
C:\Users\User\Documents\breakout_final\home.cpp:16: error: no matching
function for call to 'QObject::connect(QPushButton*&, const char*,
home*, const char*)'
QObject::connect(button3,SIGNAL(clicked()),this,SLOT(startgame1()));
^
You have an error in your code: in order to use Qt signals and slots, you should inherit your class from QObject, Q_OBJECT declaration itself is not enough:
#include <QObject>
class home : public QObject
{
Q_OBJECT
public:
home();
virtual void set_home_background()=0 ;
QGraphicsScene *scene3;
QPushButton *button3;
private slots:
virtual void startgame1();
};
I'm asking if there is a way to use signals in a class which inherits from QObject like this:
mysuperclass.cpp
#include "mysuperclass.h"
MySuperclass::MySuperclass(quint16 port, QObject *parent) :
QObject(parent), port(port)
{
this->connected = false;
}
mysuperclass.h
#include <QAbstractSocket>
class MySuperclass: public QObject
{
Q_OBJECT
public:
explicit MySuperclass(quint16 port = 0, QObject *parent = 0);
signals:
//there is nothing here
public slots:
virtual void newValue(){qDebug() << "newValue";}
virtual void connectionEstablished(){qDebug() << "connectionEstablished";}
virtual void disconnected(){qDebug() << "disconnected";}
protected:
QAbstractSocket* networkSocket;
quint16 port;
bool connected;
};
mysubclass.cpp
#include <QTcpSocket>
#include <QHostAddress>
MySubClass::MySubClass(quint16 ServerPort, QObject *parent) :
MySuperClass(ServerPort, parent)
{
this->networkSocket = new QTcpSocket(this);
...
connect(this->networkSocket, SIGNAL(connected()),this,
SLOT(connectionEstablished()));
connect(this->networkSocket, SIGNAL(disconnected()),this,
SLOT(disconnected()));
connect(this->networkSocket, SIGNAL(readyRead()),this, SLOT(newValue()));
}
mysubclass.h
#include <QObject>
#include "mysuperclass.h"
class MySubClass: public MySuperClass
{
public:
MySubClass(quint16 ServerPort, QObject* parent=0);
public slots:
void newValue();
void connectionEstablished();
void disconnected();
};
You must include the Q_OBJECT macro in the derived class too (but don't derive from QObject again). The macro is only mandatory if the derived class declares signals or slots. For emitting parent's signals or connecting with parent's slots it is not necessary (it also means that it is not necessary to re-define already existing signals or slots).
From Qt's documentation:
The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system.
Example
class MySubClass : public MySuperClass {
Q_OBJECT
public:
MySubClass(quint16 ServerPort, QObject* parent=0);
public slots:
void newValue();
void connectionEstablished();
void disconnected();
};
On the other hand, if you want to connect to a slot in the parent class but implement it in a derived one, then you must make it virtual:
class MySuperclass : public QObject {
Q_OBJECT
// ...
public slots:
virtual void newValue(); // can be virtual pure also
};
class MySubClass : public MySuperClass {
public:
virtual void newValue() override; // overrides parent's
}
Note that there is no need to use the Q_OBJECT macro nor to use the slot: label in the derived class. Slots are normal methods after all. Of course, you have to use it if you add new slots or signals.
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.
I'm using Qt 5.7 trying to use a timer with timeout event in a class named MyClass. I created a public variable of this class in mainwindow.h. I put the timer's slot connect in the constructor of MyClass, and have a function in MyClass to start the timer. But when I execute the function, the timer slot doesn't work.
I have no error in building, but I get the comment below on the application window at run time:
QObject::connect: No such slot QObject::on_timeout()
Here is my code:
The mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "myclass.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MyClass mc;
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
The mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myclass.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
mc.TimerStart();
}
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
class MyClass : public QObject
{
public:
MyClass();
TimerStart();
QTimer *timer;
public slots:
on_timeout();
};
#endif // MYCLASS_H
myclass.cpp
#include "myclass.h"
#include <QMessageBox>
#include <QTimer>
MyClass::MyClass()
{
timer = new QTimer(this);
}
MyClass::TimerStart()
{
timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
timer->start(1000);
}
MyClass::on_timeout()
{
QMessageBox msg;
msg.setText("updated");
msg.exec();
}
You forgot to add the Q_OBJECT to MyClass,
You're reentering the event loop in on_timeout.
You're setting the timer's interval multiple times.
You're connecting to the timer's signal multiple times.
You're making an implementation detail (the on_timeout slot) public.
You're pessimizing your code by manually managing the memory for QTimer.
You're including <QTimer> twice.
It's 2016 and you're not using C++11. Yes, you can use it even with Qt 4.
Here's how I'd write it:
Qt 5
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
#include <QMessageBox>
class MyClass : public QObject
{
Q_OBJECT
QMessageBox msg;
QTimer timer{this};
public:
explicit MyClass(QObject * parent = nullptr);
void timerStart();
};
#endif // MYCLASS_H
#include "myclass.h"
MyClass::MyClass(QObject * parent) : QObject{parent}
{
msg.setText(QStringLiteral("updated"));
connect(&timer, &QTimer::timeout, &msg, &QMessageBox::show);
}
void MyClass::timerStart()
{
timer.start(1000);
}
Qt 4
Here I demonstrate that implementation details should be private. You could of course do as above and set the msg's text in the constructor, and connect directly to the msg's SLOT(show()).
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
#include <QMessageBox>
class MyClass : public QObject
{
Q_OBJECT
QMessageBox msg;
QTimer timer{this};
Q_SLOT void on_timeout();
public:
explicit MyClass(QObject * parent = nullptr);
void timerStart();
};
#endif // MYCLASS_H
#include "myclass.h"
MyClass::MyClass(QObject * parent) : QObject{parent}
{
connect(&timer, SIGNAL(timeout()), SLOT(on_timeout()));
}
void MyClass::timerStart()
{
timer.start(1000);
}
void MyClass::on_timeout()
{
msg.setText("updated");
msg.show();
}
You forgot to add Q_OBJECT in your class declaration:
class MyClass : public QObject
{
Q_OBJECT
// ...
If you're using Qt 5.7, you should use the Qt5 syntax for connect:
connect(timer, &QTimer::timeout, this, &MyClass::on_timeout);
By doing so, the connection will be evaluated at compile time instead of runtime. Moreover, you can connect a signal to functions even if they are not declared as slots (so you won't need the Q_OBJECT identifier in the class declaration).
More info here.