[Solved] Multi-threaded Network and User Interface
-
What i want to do is very simple.
When my server receives data, i want to be able to display the information sent into a QTextEdit located into my MainWindow.ui file.
The problem is, whenever i try to connect one of my QThread's method to one of my MainWindow's method, i get this error :
@QObject::connect: Cannot connect (null)::dataReceived(QByteArray) to MainWindow::grabData(QByteArray)@
What am i doing wrong?
MainWindow.h
@#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "server.h"
namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();public slots:
void grabData(QByteArray);
private:
Ui::MainWindow *ui;
Server *server;
};#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);server = new Server(this); server->Start(); connect(server->thread, SIGNAL(dataReceived(QByteArray)), this, SLOT(grabData(QByteArray)));
}
MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::grabData(QByteArray msg){
QString message(msg);
ui->Txt_ChatOutput->append(message);
}@NetworkThread.h
@#ifndef NETWORKTHREAD_H
#define NETWORKTHREAD_H#include <QThread>
#include <QTcpSocket>
class NetworkThread : public QThread
{
Q_OBJECT
public:
explicit NetworkThread(int ID, QObject *parent = 0);
void run();signals:
void error(QTcpSocket::SocketError socketError);
void dataReceived(QByteArray);
public slots:
void readyRead();
void disconnected();
private:
QTcpSocket *socket;
int socketDescriptor;
};#endif // NETWORKTHREAD_H@
NetworkThread.cpp
@#include "networkthread.h"
NetworkThread::NetworkThread(int ID, QObject *parent) :
QThread(parent)
{
this->socketDescriptor = ID;}
void NetworkThread::run(){
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor)){
emit error(socket->error());
return;
}connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection); connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection); exec();
}
void NetworkThread::readyRead(){
QByteArray Data = socket->readAll();
socket->write(Data);
emit dataReceived(Data);
}void NetworkThread::disconnected(){
socket->deleteLater();
exit(0);
}@Server.h
@#ifndef SERVER_H
#define SERVER_H#include <QTcpServer>
#include "networkthread.h"class Server : public QTcpServer
{
Q_OBJECT
public:
explicit Server(QObject *parent = 0);
void Start();NetworkThread *thread;
signals:
public slots:
protected:
void incomingConnection(qintptr socketDescriptor);
};#endif // SERVER_H@
Server.cpp
@#include "server.h"
Server::Server(QObject *parent) :
QTcpServer(parent)
{
}void Server::Start(){
if(this->listen(QHostAddress::Any, 2424)){}
}
void Server::incomingConnection(qintptr socketDescriptor){
thread = new NetworkThread(socketDescriptor,this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
@ -
Server::thread only gets initialized when incomingConnection() is called.
But you do the connection right after you've created an Server-instance and called start() on it.
At this time server->thread is not yet initialized and thus there is no object to do the connection with. -
[quote author="raven-worx" date="1383577334"]Server::thread only gets initialized when incomingConnection() is called.
But you do the connection right after you've created an Server-instance and called start() on it.
At this time server->thread is not yet initialized and thus there is no object to do the connection with.[/quote]Alright, i understand.
But now, how can i fix this?I really can't think of a solution here.
If i can't connect my QThread right after creating my MainWindow object, how am i ever going to connect it if i don't have access to my User Interface outside of Main.cpp or MainWindow.h/.cpp?
-
at a quick glance you anyway use a single thread in your server design.
So quickest solution would be to create a thread instance in your Server::start() method or constructor. Just before you try to connect it...
And start the thread in Server::incomingConnection() (like you already do).