PDA

View Full Version : Signal can't be emitted !



Vladimir_
25th September 2014, 19:24
Hello,

file1.h


class MyServer : public QTcpServer
{
Q_OBJECT

.... // some code

signals:
void _connection(int);

.... // rest of the code



file1.cpp


void MyServer::incomingConnection(int handle)
{
MyClient *client = new MyClient(this);
client->setsocket(handle);
emit _connection(handle); // i emit it here
}


file2.h


#include "file1.h"
class Blabla: public QObject
{
Q_OBJECT

... // code here

private:
MyServer *server;

... // rest of code


file2.cpp


server = new MyServer;

connect(server,SIGNAL(_connection()), this, SLOT(connected())); // the slot is declared in the code


The issue:
----------
The signal is not emitted within the incoming connction.

The question:
-------------
Why ?


Thanks,
Vladimir.

ChrisW67
25th September 2014, 20:58
The code is never called. You are not running the code you think you are. You have not connected to the signal or object you think you have. There is no incoming connection, perhaps blocked by a firewall. Etc.

What have you done to debug this? Put a breakpoint in the routine? Single stepped?

Vladimir_
25th September 2014, 21:09
there's an incoming connection,



void MyServer::incomingConnection(int handle)
{
MyClient *client = new MyClient(this);
client->setsocket(handle);
QMessageBox::information(0, "connected", "new client"); // this runs, so the function worked.
emit _connection(handle); // i emit it here
}


the incomingConnection() is written in italic in the QtCreator. it's already coded.

here's a proof that the code worked:
10640

but the signal is never emitted.

wysota
25th September 2014, 23:26
How do you know the signal is not emitted? Maybe a more appropriate topic to your problem would be "slot is not called" rather than "signal is not emitted"? Can you call connected() using e.g. invokeMethod()? Do the sender and receiver belong to the same thread?

Vladimir_
25th September 2014, 23:46
I used another signal, and the slot is called.

So i made sure that the slot has no issues .

wysota
25th September 2014, 23:50
Is the connection established properly? Does connect() return true? Do you get any messages, warnings on the console when your program is running?

Vladimir_
26th September 2014, 00:34
no messages or warnings at all !

the connection istablished well, and i even get the sent data via QByteArray and display it in QMessageBox.

only this can't be emitted !!

anda_skoa
26th September 2014, 08:56
file2.cpp


server = new MyServer;

connect(server,SIGNAL(_connection()), this, SLOT(connected())); // the slot is declared in the code


The issue:
----------
The signal is not emitted within the incoming connction.

The signal is not emitted because it does not exists.

The application output would have told you that (Qt prints a warning) and the return value of the connect would have been "false".

Look at the content of the SIGNAL macro and the declaration of the signal and find the difference.

Cheers,
_


P.S.: unless you need SSL sockets, there is no need to derive from QTcpServer. I has a signal that is emitted for each incoming connection.

wysota
26th September 2014, 09:34
no messages or warnings at all !
I'm sure you are wrong about this. Maybe you are looking in the wrong place. We are talking about a runtime message to the console, not a warning during compilation.


the connection istablished well
Does connect() return true? I don't think so.

Vladimir_
26th September 2014, 15:01
connect() returns 0 , means "false" ....

What an I do now ?!

i posted all the codes I did, i need it working :p


The signal is not emitted because it does not exists.

see file1.h and file1.cpp .

what do you mean it does not exist ?

Lesiok
26th September 2014, 15:22
1. Is the class with method connected() derived from QObject ?
2. Is the method connected declared as slot ?

Vladimir_
26th September 2014, 15:44
myclient.h


class MyClient : public QObject
{
Q_OBJECT
public:
explicit MyClient(QObject *parent = 0);
void setsocket(int Descriptor);


QTcpSocket *socket;

signals:
// can't put signal here, coz incomingConnection() isn't here.
public slots:
void connected(); // here it is
void disconncted();
void readyRead();
void TaskResult(int number);
void setNum();
//.... rest of the code


myclient.cpp


void MyClient::connected()
{
QMessageBox::information(0, "connected", "bingo!");
}


Added after 8 minutes:

Okay guys .. I came up with the solution.

SIGNALS can't be emitted in the incomingConnection() function.

Maybe because it's not called manually .

I tried to create a method and emitted the signal in it.

I called the method manually then put the connect() statement .. IT WORKED!!

summary:
---------
Don't emit signals in methods which is not called by you manually in the code.

Thanks,
Vladimir.

anda_skoa
26th September 2014, 15:59
Okay guys .. I came up with the solution.

No, you just avoided the mistake you made.



SIGNALS can't be emitted in the incomingConnection() function.

Of course that is possible.
That was not the problem.

You problem was, as I already wrote earlier, that you tried to connect to a signal that did not exists.

If you had, as I suggested, checked the difference between the signal declaration and the non existing signal used in the SIGNAL macro, you would have seen that your signal had the signature


_connection(int)

but you were trying to connect to


_connection()


You can of course decide to remain ignorant to how Qt's signal/slot feature works and make up some silly rules instead.

Cheers,
_

Vladimir_
26th September 2014, 16:07
anda_soka, now I called :



int cn = connect(server,SIGNAL(_connection(int)), this, SLOT(connected()));
QMessageBox::information(0, "connect()", QString::number(cn));


the messagebox shows e that cn = 1, means connect() returns "true" after it was returning 0 "false" .

But .. the SLOT didn't work ..

EDIT: I changed to another slut , but it still won't work

wysota
26th September 2014, 17:04
"Doesn't work" is really not helpful description of a problem.

If you want us to test something, I suggest you provide a minimal compilable example reproducing the problem (10-20 lines of code).

Vladimir_
26th September 2014, 17:37
wysota, i gave all the codes in the #1 post of this thread.

But it's ok. i'll do it again with the WHOLE files "not just a snippets" :

myserver.h


#ifndef MYSERVER_H
#define MYSERVER_H

#include <QTcpServer>
#include <QTcpSocket>
#include <QAbstractSocket>
#include "mainwindow.h"

class MyServer : public QTcpServer
{
Q_OBJECT
public:
explicit MyServer(QObject *parent = 0);
void startServer(int);

protected:
void incomingConnection(int handle);

signals:
void _connection(int handle);

public slots:

private:

MainWindow *main;
QTcpSocket *socket;


};

#endif // MYSERVER_H



myserver.cpp


#include "myserver.h"
#include "myclient.h"
#include <QtGui>

MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
main = new MainWindow;
socket = new QTcpSocket;
}

void MyServer::startServer(int port)
{
if(listen(QHostAddress::Any,port))
{

QMessageBox::information(0,"started", "Server Started!!");
}
else
{
QMessageBox::warning(0,"Server not started", "Can't listen on the port "+QString::number(port))+".<br>"
"please change the port.<br>This happened because the port is busy.";
}
}

void MyServer::incomingConnection(int handle)
{
MyClient *client = new MyClient(this);
client->setsocket(handle);
emit _connection(handle);
}



myclient.h


#ifndef MYCLIENT_H
#define MYCLIENT_H

#include <QObject>
#include <QTcpSocket>
#include <QDebug>
#include <QThreadPool>
#include <QtGui>
#include "mytask.h"
#include "myserver.h"
#include "mainwindow.h"


class MyClient : public QObject
{
Q_OBJECT
public:
explicit MyClient(QObject *parent = 0);
void setsocket(int Descriptor);
void clientConnected();


QTcpSocket *socket;

signals:
void isConnected();

public slots:
void connected();
void disconncted();
void readyRead();
void TaskResult(int number);
void setNum();

private:
MyClient *client;
MainWindow *main;

MyServer *server;

};

#endif // MYCLIENT_H




myclient.cpp


#include "myclient.h"

MyClient::MyClient(QObject *parent) :
QObject(parent)
{
QThreadPool::globalInstance()->setMaxThreadCount(5);


}


void MyClient::setsocket(int Descriptor)
{

socket = new QTcpSocket;

main = new MainWindow;

server = new MyServer;

clientConnected();

int cn = connect(server,SIGNAL(_connection(int)), this, SLOT(connected()));
QMessageBox::information(0, "cinnect()", QString::number(cn));
connect(socket, SIGNAL(disconnected()), this, SLOT(disconncted()));
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));



socket->setSocketDescriptor(Descriptor);


}


void MyClient::connected()
{

QMessageBox::information(0, "connected", "bingo!");
}

void MyClient::disconncted()
{
qDebug() << "client disconnected!";
// test -= 1;
}

void MyClient::clientConnected()
{
QByteArray handshake = socket->readAll();

if(handshake == "newClient")
{

emit isConnected();

}
}

void MyClient::readyRead()
{


// time consumer
MyTask *mytask = new MyTask();
mytask->setAutoDelete(true);
connect(mytask, SIGNAL(Result(int)), this, SLOT(TaskResult(int)), Qt::QueuedConnection);
QThreadPool::globalInstance()->start(mytask);
}

void MyClient::TaskResult(int number)
{
QByteArray Buffer;
Buffer.append("Task Result = ");
Buffer.append(QString::number(number));

socket->write(Buffer);

}

void MyClient::setNum()
{
emit isConnected();
}

wysota
26th September 2014, 18:18
wysota, i gave all the codes in the #1 post of this thread.
Something that doesn't have a main function is certainly not compilable.


But it's ok. i'll do it again with the WHOLE files "not just a snippets" :
Still no main() and still not minimal. You are missing the point of this exercise. If you "test" 200 lines of code containing many classes not at all related to the problem you are dealing with then there is too much external influence to focus on the real problem. If you have problems with establishing a signal-slot connection then strip out all code but the one related to that connection. I doubt TaskResult class or a thread pool are going to help you isolate the problem. So either remove code from what you have now or build an example starting with an empty project and filling it with your code. There is a good chance the problem will smack you in your face without us helping.

By the way I don't think code for setting a maximum number of threads on the default thread pool belongs to a constructor of a TCP client class. Probably also creating a main window in a function for setting a socket descriptor is not the best approach too.

And also start using qDebug() instead of QMessageBox for getting debug output from your programs.

Vladimir_
26th September 2014, 20:05
Ok bros,
I created an individual project for the signals and slots, and i got the same problem.
NOTE: it's a Gui application.

files:
mainwindow.h | mainwindow.cpp | main.cpp

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);
void callSignal();
~MainWindow();

signals:
void _connected(int);


private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H



mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtGui>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

callSignal();
bool c = connect(this,SIGNAL(_connected(int)), this, SLOT(close()));
QMessageBox::information(0, "Connect()", QString::number(c)); // shows c = 1 "true"
}

void MainWindow::callSignal()
{
emit _connected(1);
}

MainWindow::~MainWindow()
{
delete ui;
}



main.cpp


#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}



the connect() returns "true" , but the signal isn't working.

So this simple project has the secret why, i hope you find it.

Thanx.

stampede
26th September 2014, 20:43
Maybe because you are calling a signal before making a connection ?

Vladimir_
26th September 2014, 20:50
stampede, i tried to call the signal after the connection, nothing happens.

stampede
26th September 2014, 21:02
i tried to call the signal after the connection, nothing happens.
Ok, but if you "emit" a signal in constructor, which in fact simply calls "close" on a "newborn" widget, and then call show() on it again (main.cpp:8), it may look like nothing happened. Connect this signal to custom slot and qDebug() << something in that slot or set a breakpoint.

Vladimir_
26th September 2014, 21:12
I did connect to a custom slot and that has the same consequence, that's why I did a predefined slot.

Can you please compile this in your pc and troubleshoot for me ?

It would be better to know the issue.

stampede
26th September 2014, 21:19
It is not possible without the .ui file.

Vladimir_
26th September 2014, 21:26
you can simply create a new project and copy these codes...

stampede
26th September 2014, 21:36
Sorry but I'm using command line + notepad, it does not have a "new project" option. Maybe someone else will be able to help you.

Vladimir_
26th September 2014, 22:35
Ok, this is the mainwindow.ui



<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

stampede
27th September 2014, 08:53
There is no problem with this code, if you emit the signal after making the connection, everything works as expected.


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
void callSignal();
~MainWindow();

private slots:
void test();

signals:
void _connected(int);


private:
Ui::MainWindow *ui;
};

#endif



#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtGui>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

bool c = connect(this,SIGNAL(_connected(int)), this, SLOT(test()));
callSignal();
QMessageBox::information(0, "Connect()", QString::number(c)); // shows c = 1 "true"
}

void MainWindow::callSignal()
{
emit _connected(1);
}

void MainWindow::test(){
QMessageBox::information(0, "slot", "test");
}

MainWindow::~MainWindow()
{
delete ui;
}

anda_skoa
27th September 2014, 13:25
You are calling show() after the signal has called close().

Does "nothing happens" mean that the window is shown or that it is not?

I would expect it to be shown, that is the last thing it is told to do.

Cheers,
_

Vladimir_
27th September 2014, 15:22
it is shown.

and i used slots like maximizing the window ...etc but none is called.

wysota
27th September 2014, 15:26
it is shown.

and i used slots like maximizing the window ...etc but none is called.

With emitting the signal before or after the connect() statement?

Vladimir_
27th September 2014, 16:38
emitting before the connect() statement. I corrected thhe source code ..

i didn't expect to be stuck like this in signals and slots

Added after 50 minutes:

Guys, please compile it on your machines and tell me what happens ... maybe it's just from my compiler

Vladimir_
27th September 2014, 17:53
Okay, now it works.

i made the connect() before the emit statement, then corrected the signal.

thanks

wysota
27th September 2014, 20:31
emitting before the connect() statement. I corrected thhe source code ..

i didn't expect to be stuck like this in signals and slots

Added after 50 minutes:

Guys, please compile it on your machines and tell me what happens ... maybe it's just from my compiler

If you emit a signal before making a connection, then obviously this signal emission will not be affected by the connection. C++ is an imperative language, order of statements matters.