circular dependency QThread - c++

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.

Related

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().

Slots and signals in QThread

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.

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.

Qt creating a class and using in a vector

I'm new in Qt and C++. I want to implement a vector with using a class called Item. I think I'm doing a beginners mistake. I'm getting the below error. Can someone please help?
C:\Qt\Qt5.6.1\5.6\msvc2015_64\include\QtCore\qvector.h:631: error: C2280: 'Item::Item(const Item &)': attempting to reference a deleted function
Below is my mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVector>
#include <QtCore>
#include <QtGui>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::AddRoot(QString item)
{
QTreeWidgetItem *itm = new QTreeWidgetItem(ui->treeWidget);
itm->setText(0,item);
ui->treeWidget->addTopLevelItem(itm);
}
void MainWindow::AddChild(QTreeWidgetItem *parent,QString item)
{
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
Item item;
item.setDescription(ui->lineEdit->text());
data.push_back(item);
ui->treeWidget->setColumnCount(1);
AddRoot(item.getDescription());
}
And my item.cpp class
#include "item.h"
#include <QtCore>
#include <QtGui>
Item::Item()
{
}
void Item::setDescription(QString desc)
{
Description = desc;
}
void Item::setEnterDate(QDateTime enterDate)
{
EnterDate = enterDate;
}
void Item::setEndDate(QDateTime endDate)
{
EndDate = endDate;
}
QString Item::getDescription()
{
return Description;
}
QDateTime Item::getEnterDate()
{
return EnterDate;
}
QDateTime Item::getEndDate()
{
return EndDate;
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <item.h>
#include <QtGui>
#include <QtCore>
#include <QTreeWidget>
mainwindow.h:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QVector<Item> data;
void AddRoot(QString item);
void AddChild(QTreeWidgetItem *parent,QString item);
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
item.h:
#ifndef ITEM_H
#define ITEM_H
#include <QtCore>
#include <QtGui>
class Item : public QObject
{
Q_OBJECT
public:
explicit Item(QObject *parent = 0);
QString Description;
QDateTime EnterDate;
QDateTime EndDate;
QString getDescription();
QDateTime getEnterDate();
QDateTime getEndDate();
void setDescription(QString desc);
void setEnterDate(QDateTime enterDate);
void setEndDate(QDateTime endDate);
};
#endif // ITEM_H
Item is a QObject. QObjects are know for not having a copy constructor. In order to use the QVector, the item needs to have a copy constructor. Either change Item to not being a QObject, or use QSharedPointer (but only if you understand ownership).

Error :No match for operator ">>" in Qt

I have written a client GUI to receive structure from server. When I compile, I receive the error:
error: no match for 'operator>>' in 'is >>
newstruct.basestruct::element1'
Can you point me where I have gone wrong?
dialog.cpp:
#include "dialog.h"
#include "ui_dialog.h"
#include <QString>
#include <QDebug>
#include <QTextStream>
#include <QDataStream>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
ui->pushButton->setText("Connect");
ui->pushButton_2->setText("Ok");
ui->pushButton_3->setText("Close");
ui->pushButton_4->setText("Disconnect");
}
Dialog::~Dialog()
{
delete ui;
}
QDataStream& operator >>(QDataStream& is,const basestruct& newstruct)
{
is >> newstruct.element1;
qDebug()<<newstruct.element1;
}
void Dialog::Read()
{
socket->waitForReadyRead(-1);
QDataStream receiveData(socket);
receiveData.setVersion(QDataStream::Qt_4_0);
receiveData >>newstruct ;
}
void Dialog::on_pushButton_clicked()
{
socket=new QTcpSocket(this);
socket->connectToHost("127.0.0.1",5000);
if (socket->waitForConnected(-1))
qDebug()<<"Connected";
Read();
}
void Dialog::on_pushButton_4_clicked()
{
socket->close();
qDebug()<<"Disconnected";
}
dialog.h:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QTcpSocket>
namespace Ui {
class Dialog;
}
struct basestruct
{
int element1;
int element2;
};
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
void Read();
private slots:
void on_pushButton_clicked();
void on_pushButton_4_clicked();
private:
Ui::Dialog *ui;
QTcpSocket *socket;
friend Q_CORE_EXPORT QDataStream &operator >>(QDataStream&,const struct basestruct&);
struct basestruct newstruct;
};
#endif // DIALOG_H