How to constantly read UDP packets in QT? - c++

I am sending myself UDP packets generally using this method here:
How to receive proper UDP packet in QT?
I am setting up modes so that in Write mode, it sends UDP packets every second, and in Read mode, it just receives packets. To do this I set up a simple boolean variable called readmode when readmode = true it reads and writes when = false. I left the connect(socket, SIGNAL(readyRead()), this,SLOT(readyRead())); and the call to the send function in the MainWindow constructor and put the if statements, testing the state of readMode to actually do something, in the send function and readyRead() function themselves.
My problem is that I only receive packets whenever I start the program in Read mode first before opening the window for the program to write. If I start sending packets before I open the Read program, I get nothing.
For clarification I am opening two instances of this program and I set one to Read and the other to Write, but the Read has to be started first for it to work, but once states are changed, it stops working.
How can I get it to read all the time?
Code sample:
bool readMode = true; //Write mode = false, Read Mode = true
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
timer = new QTimer(this);
timer->start(1000);
ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Read");
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText("Write");
out_socket = new QUdpSocket(this);
out_socket->bind(60500);
in_socket = new QUdpSocket(this);
in_socket->bind(60510);
connect(timer, SIGNAL(timeout()),this,SLOT(UDP_test()));
connect(in_socket,SIGNAL(readyRead()),this,SLOT(readyRead()));
}
void MainWindow::UDP_test() //Write Mode
{
if (readMode == false) //Write Mode
{
QByteArray Data;
Data.append(fullResultString);
out_socket->writeDatagram(Data,QHostAddress("192.168.127.10"),60510);
}
void MainWindow::readyRead() //Read Mode
{
if (readMode == true) //Readmode
{
while(in_socket->hasPendingDatagrams())
{
QByteArray UDPBuffer;
UDPBuffer.resize(in_socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
in_socket->readDatagram(UDPBuffer.data(),UDPBuffer.size(), &sender, &senderPort);
}

That's to be expected: each invocation of the process attempts to bind the input socket. The first time, with the socket not bound yet - it succeeds. The second time - it fails, as the port is already bound - so reading won't work. Everything aside, the code never checks for errors, and thus leaves the user (i.e. you) unaware that things have failed. With error checking it'd be obvious why it doesn't work. The output socket doesn't need to be bound to an explicitly specified port number. The input socket should only be bound when the program is in receive mode.

QUdpSocket doesn't emit readyRead if it already contains (not read) datagramms when it receives a new datagram. You source code doesn't complete. So we can't see how do you change your global variable 'readMode'.
here the simple demo application:
#include <QApplication>
#include <QWidget>
#include <QUdpSocket>
#include <QPushButton>
#include <QListWidget>
#include <QGridLayout>
#include <QDebug>
#include <QUuid>
int main( int argc, char** argv ) {
QApplication app( argc, argv );
QWidget form;
auto*const log_widget = new QListWidget( &form );
auto*const client = new QUdpSocket( qApp );
auto*const server = new QUdpSocket( qApp );
const quint16 TEST_PORT = 31088;
if( ! server->bind( QHostAddress::LocalHost, TEST_PORT ) ) {
exit( 1 );
}
QObject::connect( server, &QUdpSocket::readyRead, [=]() {
log_widget->insertItem( 0, "readyRead() has been received" );
});
auto*const write_button = new QPushButton( "&Write", &form );
QObject::connect( write_button, &QPushButton::clicked, [=]() {
const auto packet = QUuid::createUuid().toByteArray();
client->writeDatagram( packet, QHostAddress::LocalHost, TEST_PORT );
log_widget->insertItem( 0, "A datagram has been sent." );
});
auto*const read_button = new QPushButton( "&Read", &form );
QObject::connect( read_button, &QPushButton::clicked, [=]() {
if( server->hasPendingDatagrams() ) {
const int size = static_cast< int >( server->pendingDatagramSize() );
if( size > 0 ) {
QByteArray packet;
packet.resize( size );
server->readDatagram( packet.data(), size );
log_widget->insertItem( 0, "Read OK: datagram have been read." );
} else {
log_widget->insertItem( 0, "Read Error: invalid datagram size." );
}
} else {
log_widget->insertItem( 0, "Read Error: there is no any datagram." );
}
});
auto*const check_button = new QPushButton( "&Check", &form );
QObject::connect( check_button, &QPushButton::clicked, [=]() {
if( server->hasPendingDatagrams() ) {
log_widget->insertItem( 0, "Check: there is at least one datagram." );
} else {
log_widget->insertItem( 0, "Check: there is no any datagram." );
}
});
auto*const grid = new QGridLayout( &form );
grid->addWidget( write_button, 0, 0 );
grid->addWidget( read_button, 0, 1 );
grid->addWidget( check_button, 0, 2 );
grid->addWidget( log_widget, 1, 0, 1, 3 );
form.show();
return app.exec();
}

Related

Server does not read from clients

Gist of the program: The server creates n client processes. On the client, the user enters a character string that is sent to the server. On the server, the string is processed as follows: the frequency of occurrence of vowels and numbers in the entered string is calculated. This information is then sent to the client.
Two programs (server and clients) were based on console editions(They works perfectly). When I add QT support to server, console clients and gui server works fine, but when i add gui to client - it stop working and i don't know what to do.
I guess the problem is not even named pipes, but clumsy code in terms of Qt (in client). The client outputs that a connection to the server has been established, and the server indicates that it cannot read a string from the pipe.
Server can create n gui clients and then, when i try to write string to client, client closes.
Code of the client:
gui_pipe_client.h:
#pragma once
#include <LotsOfLibraries...>
class Window : public QWidget {
Q_OBJECT // этот макрос должен включаться в классы, которые объявляют свои собственные сигналы и слоты
private:
HANDLE. m_hndlNP;
public:
Window(QWidget *parent = 0, HANDLE m_hndlNP = NULL);
private slots:
int OnSend();
private:
QLabel *lbl;
QLineEdit *textfield;
QPushButton *button_send;
};
gui_pipe_client.cpp:
#include "gui_pipe_client.h"
#include <QGridLayout>
#include <thread> //!NEW!
using namespace std;
#define PIPE_TIMEOUT 5000
#define BUFSIZE 4096
Window::Window(QWidget *parent, HANDLE hndlNP)
: QWidget(parent), m_hndlNP(hndlNP){
QLineEdit *textfield = new QLineEdit(this);
textfield->setPlaceholderText("Enter string...");
QPushButton *button_send = new QPushButton("Send", this);
QPushButton *button_quit = new QPushButton("Quit", this);
lbl = new QLabel("kjiqofj13fjio2;3fjl;3jiofj2l3;fij3;fioj423j;fj32jf;o3f", this);
lbl->setWordWrap(true);
QGridLayout *grid = new QGridLayout(this);
grid->addWidget(textfield, 0, 0);
grid->addWidget(button_send, 1, 0);
grid->addWidget(button_quit, 2, 0);
grid->addWidget(lbl, 3, 0);
setLayout(grid);
connect(button_send, &QPushButton::clicked, this, &Window::OnSend); // привязка сигнала и слота
connect(button_quit, &QPushButton::clicked, qApp, &QApplication::quit); // signal - slot
}
int Window::OnSend() {
button_send->setEnabled(false);
char text[1024];
const QByteArray stringData = textfield->text().toUtf8();
//char text[100];
text[qMin(1023,stringData.size())]='\0';
std::copy(stringData.constBegin(),stringData.constBegin()+qMin(1023,stringData.size()),text);
printf("%s", text);
char answer[1024];
DWORD read_bytes;
DWORD written_bytes;
if (WriteFile(m_hndlNP, text, 1024, &written_bytes, NULL)) {
if (!ReadFile(m_hndlNP, answer, 1024, &read_bytes, NULL)) {
//printf("ReadFile failed with %d.\n", GetLastError());
system("pause"); // TEMPORARY
//return EXIT_FAILURE;
}
}
else {
printf("WriteFile failed with %d.\n", GetLastError());
system("pause"); // TEMPORARY
//return EXIT_FAILURE;
}
//cout << "Writting and reading was successful\n";
lbl->setText((QString) (answer));
// ***CLOSING PIPE CONNECTION***
CloseHandle(m_hndlNP);
//QApplication::quit();
}
main.cpp:
#include "gui_pipe_client.h"
using namespace std;
int main(int argc, char *argv[]) {
cout << "Client is launched\n";
HANDLE hndlNP = CreateFile(
TEXT("\\\\.\\pipe\\os_lab4_pipe"),
GENERIC_READ | GENERIC_WRITE,
NULL, // Prevents other processes from opening a file or device
NULL, // cannot be inherited by any child processes
OPEN_EXISTING,
NULL, // no attributes
NULL // no template
);
if (hndlNP == INVALID_HANDLE_VALUE) {
printf("CreateFile error\n");
cout << "CreateFile error\n";
//return EXIT_FAILURE;
}
cout << "Pipe connection established\n";
QApplication app(argc, argv);
Window window(0, hndlNP);
window.resize(600, 600);
window.setWindowTitle("Pipe client");
window.show();
return app.exec();
}

Why does my worker thread not receive this signal?

I have my main thread which is in charge with the GUI and my worker thread which is in charge with doing stuff with my webcam.
I am able to emit a signal from my main thread to my webcam thread, but it never receives it! Could somebody explain me why?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setThreadsAndObj();
setConnects();
startCamera();
}
void MainWindow::setThreadsAndObj()
{
cameraClassPtr = new cameraClass();
cameraThread = new QThread();
}
void MainWindow::setConnects()
{
....
connect(this, &MainWindow::savePicture, cameraClassPtr, &cameraClass::takePicture);
}
void MainWindow::startCamera()
{
//camera start
connect( cameraThread, &QThread::started, cameraClassPtr, &cameraClass::getVideoFrame );
connect( cameraThread, &QThread::finished, cameraClassPtr, &QThread::deleteLater );
connect( cameraThread, &QThread::finished, cameraThread, &QThread::deleteLater );
//receive camera frames
connect(cameraClassPtr, &cameraClass::videoFrameToGui, this, &MainWindow::updateCameraStream);
//start threads
cameraClassPtr->moveToThread(cameraThread);
cameraThread->start();
}
void MainWindow::foo()
{
emit savePicture();
}
void cameraClass::takePicture()
{
qDebug()<<"camera class received signal"; //THIS NEVER GETS PRINTED
}
Could someone explain me why my signal is never received and "camera class received signal" is never printed and how to solve this?
I had this loop in my worker thread:
...
static cv::VideoCapture cap(-1);
if( !cap.isOpened() )
{
qDebug()<< "Could not initialize capturing...\n";
}
qDebug()<<"starting live camera";
cap.set(CV_CAP_PROP_FRAME_WIDTH,240);
cap.set(CV_CAP_PROP_FRAME_HEIGHT,320);
while(1)
{
cap >> imgFrame;
int fd = open("/home/John/Desktop/mainImglock.txt", O_RDWR |O_CREAT, 0666);
int rc = flock(fd, LOCK_EX | LOCK_NB);
if(rc==0)
{
cv::imwrite("/home/John/Desktop/camera.jpg", imgFrame);
}
flock(fd, LOCK_UN);
close(fd);
}
I solved the issue by adding: QApplication::processEvents(); in the while(1) loop, so that the event loop isn't hanging.
You need to subclass QThread and call QThread::exec(); in order to process events in this thread.

QTcpSocket gets NULL after QTcpServer::nextPendingConnection()

So I have a QTcpServer here (simplified version of Qt's Fortune Server Example). It was working fine earlier. Then I moved some things around and changed some code. Now my server crashes on start. As far as I can tell, after
tcpSocket = tcpServer->nextPendingConnection();
tcpSocket remains NULL. Thus all calls like tcpSocket->anyCall() will cause a seg fault. Application output shows:
QObject::connect: invalid null parameter
So my question is, why is tcpServer->nextPendingConnection() returning NULL
all of a sudden, when before I moved things around it worked just fine?
Here are the relevant parts of my code:
#include <QtWidgets>
#include <QtNetwork>
#include "server.h"
Server::Server(QWidget *parent)
: QDialog(parent), statusLabel(new QLabel), tcpServer(Q_NULLPTR), tcpSocket(Q_NULLPTR), networkSession(0), blockSize(0), userAuthenticated(false)
{
QNetworkConfigurationManager manager;
QNetworkConfiguration config = manager.defaultConfiguration();
networkSession = new QNetworkSession(config, this);
sessionOpened();
...
// GUI stuff here //
...
this->read_newClient();
}
void Server::sessionOpened()
{
tcpServer = new QTcpServer(this);
// some if else checks here //
tcpSocket = tcpServer->nextPendingConnection(); // problem here //
connect(tcpSocket, &QAbstractSocket::disconnected, tcpSocket, &QObject::deleteLater); // line that crashes //
}
void Server::read_newClient()
{
QString data;
if (!clientSocket->waitForReadyRead())
{
qDebug() << "Cannot read";
return;
}
data = readData();
}
To use nextPendingConnection you need incomming connection. Therefore you have two ways:
Connect to signal newConnection():
...
connect(tcpServer, &QTcpServer::newConnection, this, &Server::OnNewConnection);
...
void Server::OnNewConnection() {
if (tcpServer->hasPendingConnections()) {
tcpSocket = tcpServer->nextPendingConnection();
connect(tcpSocket, &QAbstractSocket::disconnected, tcpSocket, QObject::deleteLater);
}
}
Or use blocking call waitForNewConnection():
if (tcpServer->waitForNewConnection()) {
if (tcpServer->hasPendingConnections()) {
tcpSocket = tcpServer->nextPendingConnection();
connect(tcpSocket, &QAbstractSocket::disconnected, tcpSocket, QObject::deleteLater);
}
}
Do not forget call tcpServer->listen();

client program crashes when connect to server after disconnect Qt

I am implementing client side of TCP-Ip server based on Qt but the program crashes when I closed connection and start again by hitting connect button.
Overview of project. I have Qwidget ( main application) with 2 lineEdit for user to input port number and server Ip address.
It also has 2 button that connect to server and disconnect. On hitting connect button , it will call constructor of client socket and call connectToHost.
Testing: Tried testing on same computer with server running on port 6000 and ip address 127.0.0.1.
Problem: When I launch Client application.And input port number and address and hit connect button it connects successfully. And I can write to server successfully. then I click disconnect button and it disconnects successfully but after that if I connect again by clicking connect button it crashes. I know problem is with tcpSocket but have no idea how to fix it.
clientAgent( QWidget appilciation ).h
namespace Ui {
class ClientAgent;
}
class ClientAgent : public QWidget
{
Q_OBJECT
public:
explicit ClientAgent(QWidget *parent = 0);
~ClientAgent();
private:
Ui::ClientAgent *ui;
ClientForTest *tcpSockForTest;
// Qwidget declartion
below
....
private slots:
void startClient();
void stopClient();
public slots:
void getCliReqTextChanged();
};
ClientAgent.cpp
ClientAgent::ClientAgent( QWidget *parent ) :
QWidget(parent),
ui( new Ui::ClientAgent )
{
// Widget declartion and initilisation
// Layout design etc
//define signals and slots for Client
// signals and slots
connect( btnStartClient, SIGNAL( clicked() ), this, SLOT( startClient() ) );
connect( btnStopClient, SIGNAL( clicked() ), this, SLOT( stopClient() ) );
// for write
connect( lEditCliReq, SIGNAL( textChanged(const QString& ) ), this, SLOT( getCliReqTextChanged() ) );
ui->setupUi( this );
}
ClientAgent::~ClientAgent()
{
delete ui;
}
void ClientAgent::startClient()
{
qDebug() << " we are in strt Clinet";
qDebug() << " connecting ";
// get server address and port number from GUI
QString testAddr = lEditAddr->text();
QString testPort = lEditPrt->text();
tcpSockForTest = new ClientForTest( testAddr, testPort.toInt(), this );
if( tcpSockForTest->connectToServer() == true )
{
lblCliStatus->setText(" connected ....");
}
else
{
lblCliStatus->setText(" failed to connect....");
}
}
void ClientAgent::stopClient()
{
qDebug() << " disconnecting ";
tcpSockForTest->disconnectToServer();
delete tcpSockForTest;
}
ClientForTest.h
class ClientForTest : public QObject
{
Q_OBJECT
public:
ClientForTest( QString hostAddr, quint16 portNum, QObject *parent );
bool connectToServer();
void disconnectToServer();
QString getStoreMsgFrmCliReq( ) const;
void writeToTest(const QString& stripCmd );
void executeSignals();
~ClientForTest();
signals:
void sigSendData();
public slots:
void connectedToTest();
void connectionClosedByServer();
void error();
private:
QTcpSocket *sockFortest;
QString hostName;
quint16 portNumber;
quint16 nextBlockSize;
QString storeLineEditMsg;// store message from lineEditCliReq;
};
ClientForTest.cpp
ClientForTest::ClientForTest( QString hostAddr, quint16 portNum, QObject *parent ) :
hostName( hostAddr ),
portNumber( portNum ),
QObject( parent )
{
connect( sockFortest, SIGNAL( connected() ), this, SLOT( connectedToTest() ) );
connect( sockFortest, SIGNAL( disconnected() ), this, SLOT( connectionClosedByServer() ) );
connect( sockFortest, SIGNAL( error( QAbstractSocket::SocketError ) ), this, SLOT( error() ) );
storeLineEditMsg = "";
}
void ClientForTest::executeSignals()
{
// actually I need toplace itin constructor will do later on
connect( this, SIGNAL( sigSendData() ), this, SLOT( connectedToTest() ) );
}
ClientForTest::~ClientForTest()
{
sockFortest->close();
delete sockFortest;
}
bool ClientForTest::connectToServer()
{
sockFortest = new QTcpSocket( this->parent() ); // COULD be Probelm here but how to fix it?
sockFortest->connectToHost( hostName, portNumber );
nextBlockSize = 0;
executeSignals();
return sockFortest->waitForConnected(1000);
}
void ClientForTest::disconnectToServer()
{
sockFortest->close();
//sockFortest.close();
qDebug() << "in disconnect for Test ";
emit updateLabelinParent( updateStatusDis );
}
void ClientForTest::connectionClosedByServer()
{
qDebug() << "connection closed by server ";
if( nextBlockSize != 0xFFFF )
{
disconnectToServer();
}
}
void ClientForTest::error()
{
qDebug() << "in error ";
disconnectToServer();
}
void ClientForTest::writeToTest( const QString& stripCmd )
{
storeLineEditMsg = stripCmd;
if( sockFortest->state() == QTcpSocket::UnconnectedState )
{
sockFortest->close();
delete sockFortest;
sockFortest = new QTcpSocket( this->parent() );
if( connectToServer() == true )
{
qDebug() << " YEEEE CONNECTED AGAIN finally ";
}
}
if( sockFortest->state() == QTcpSocket::ConnectedState )
{
qDebug() << " YEEEE CONNECTED";
sigSendData();
}
}
void ClientForTest::connectedToTest( )
{
QByteArray block;
QDataStream out( &block, QIODevice::WriteOnly );
out.setVersion( QDataStream::Qt_4_3 );
QString stripCmd = getStoreMsgFrmCliReq(); // received info for some other function I havnt shown that func here
out << quint16( 0 ) << stripCmd;
out.device()->seek( 0 );
out << quint16( block.size() - sizeof( quint16 ) );
qDebug()<<" yeeeee connected state...";
sockFortest->write( block );
//reset storeLineEditMessage
storeLineEditMsg.clear();
}
A few things, that could all together be responsible for your crash:
you connect the signals inside the ClientForTest constructor, but the socket itself is created later. That won't work. Move the line sockFortest = new QTcpSocket(this); to the constructor, before connecting
Same line, use this instead of this->parent()
And finally: There are multiple places you create/delete the socket. Don't do it. Create the socket inside the constructor with this as parent, and that's it. In your connectToServer, establish the connection, and in disconnectToServer, close it using disconnectFromHost. Same goes for the startClient and stopClient. Create the object once and just use the connect/disconnect functions, no deleting.
If code is required, I can add some.
Since it was requested, here is some more explanation:
Of course you can use parent, but in your case, the ClientForTest is an QObject, too. If you set the ClientForTest as as parent of the socket and the widget as the parent of ClientForTest, they will be both cleaned up properly. If you use this->parent(), both will be destroyed "at the same time". However, one comes first and somtimes Qt changes the order, so your socket could be destroyed before the ClientForTest. The destructor of ClientForTest would crash. That won't happen if the socket is a child of the ClientForTest
The main difference between close() and disconnectFromHost() is that the first actually closes the OS socket, while the second does not. The problem is, after a socket was closed, you cannot use it to create a new connection. Thus, if you want to reuse the socket, use disconnectFromHost() otherwise close()
And regarding 3. and 4.:
What you are doing is creating the ClientForTest when the user clicks connect, and delete it as soon as he clicks disconnect. But thats no good design (IMHO). Since tcpSockForTest already is a member of the class, create it (via new) inside the constructor, and delete it in the destructor (optionally, because if you pass the widget as parent, Qt will delete it for you).

how to modify values of dynamically created Widget from different class QT/C++

I know this question has been asked few times but all suggestions given there doesn't work for me.
Overview: I am implementing client server model and wants that as soon as msg arrived in server it should get displayed in main Qt widget. the widget , I choose to display msg is QLineEdit.
I have 3 files in project at the moment. Agent_A which is has all widget created dynamically. Then Server_test based on QTCPServer and sockClient for socket connection. I have received message on sockclient successfully from client but I don't know how to display it correctly on Agent_A .
I have added function in socketClient.cpp to update function in Agent_A but I guess when creating instance it always being NULL.
First a small snippet of my code and then what I have tried. may be you guys can input some valuable info.
Agent_A.h
class Agent_A : public QWidget
{
Q_OBJECT
public:
explicit Agent_A(QWidget *parent = 0);
void setLineEdit( const& modifyStr ); // function to change lineEditCmdString
~Agent_A();
private:
Ui::Agent_A *ui;
QPushButton *buttonStartServer;
QPushButton *buttonStopServer;
// some other widgets
QLabel *labelDisplay;
QLineEdit *lineEditCmdString;// I want to modify this value from sock client
ServerTest *server;
// few slots defined here
}
Agent_A.cpp
Agent_A::Agent_A( QWidget *parent ):
QWidget( parent ),
ui( new Ui::Agent_A )
{
//define push buttons
buttonStartServer = new QPushButton( tr( "&Start Server" ) );
buttonStopServer = new QPushButton( tr( "S&top" ));
// some properties of other widgets defined here which is not relevant to mention here
labelDisplay = new QLabel( tr("DisplayMessgae" ) );
lineEditCmdString = new QLineEdit;// I want to modify this value on sock client
labelDisplay->setBuddy( lineEditCmdString );
// define signals and slots for Server
connect( buttonStartServer, SIGNAL( clicked() ), this, SLOT( startServers() ) );
connect( buttonStopServer, SIGNAL( clicked() ), this, SLOT( stopServer() ) );
// some layout here which agian is not important to mention here.
ui->setupUi( this );
}
Agent_A::~Agent_A()
{
delete ui;
}
void Agent_A::setLineEdit( const Qstring& modifyStr )
{
lineEditCmdString->setText( modifyStr );
}
// now by socket client which creates socket
sockClient.h
class SockClient : public QObject
{
Q_OBJECT
public:
explicit SockClient( QObject *parent, QTcpSocket* socket= 0 );
~SockClient();
// I have added this function to update QLIneEdit in Agent_A
void updateTextinParent(const QString &changeText);
signals:
private slots:
void readClient();
private:
// some other functions
QTcpSocket *socketClient;
quint16 nextBlockSize;
public slots:
};
sockclient.cpp
// constructor for sockclient and some other functions
SockClient::SockClient( QObject *parent, QTcpSocket* socket ) : QObject( parent )
{
socketClient = socket ;
// create signals and slots
connect( socketClient, SIGNAL( readyRead() ), this, SLOT( readClient() ) );
connect( socketClient, SIGNAL( disconnected() ), this, SLOT( deleteLater() ) );
}
SockClient::~SockClient()
{
socketClient->close();
delete socketClient;
}
void SockClient::readClient()
{
QDataStream clientReadStream( socketClient );
clientReadStream.setVersion( QDataStream::Qt_4_3 );
QString strRecvFrm;
quint8 requestType;
clientReadStream >> nextBlockSize;
clientReadStream >> requestType;
if( requestType == 'S')
{
clientReadStream >> strRecvFrm;
}
qDebug() << " the string is " << strRecvFrm; // Has recieved correctly from client
updateTextinParent( strRecvFrmMops ); // Now trying to update widget
socketClient->close();
}
void SockClient::updateTextinParent( const QString& changeText )
{
if( this->parent() == 0 )
{
qDebug() << " Parent not assigned"; // This get printed ..
}
Agent_A *agent = qobject_cast< Agent_A* >( this->parent() ); // ?? is this is right way to do..?
if( agent != NULL )
{
qDebug() << " we are in updateTextin" << changeText; // it never get printed so I assume instance is always nULL
agent->setLineEdit( changeText );
}
}
// ServerTest.cpp where instance of sockClient is created
ServerTest::ServerTest(QObject *parent) : QObject(parent)
{
server = new QTcpServer( this );
}
void ServerTest::startServer()
{
connect( server, SIGNAL( newConnection() ), this, SLOT( incomingConnection() ) );
if( !server->listen( QHostAddress::Any, 9999) )
{
qDebug() << " Server failed to get started";
}
else
{
qDebug() << " Server started";
}
}
void ServerTest::stopServer()
{
server->close();
qDebug() << "Server closed";
}
ServerTest::~ServerTest()
{
server->close();
delete socketforClient;
delete server;
}
void ServerTest::incomingConnection()
{
socketforClient = new SockClient(this->parent(), server->nextPendingConnection() );
}
This is a very simple example:
qt.pro:
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
# Input
HEADERS += classes.h
SOURCES += main.cpp
classes.h:
#include <QObject>
#include <QDebug>
class Agent_A : public QObject
{
Q_OBJECT
public slots:
void updateText(const QString &changeText) {
qDebug() << "updateText: " << changeText;
};
};
class SockClient : public QObject
{
Q_OBJECT
signals:
void updateTextinParent(const QString &text);
public:
void incomingText(const QString &text) {
emit updateTextinParent(text);
};
};
main.cpp:
#include "classes.h"
int main(int argc, char **argv) {
Agent_A *agent = new Agent_A;
SockClient client;
QObject::connect(&client, SIGNAL(updateTextinParent(const QString &)),
agent, SLOT(updateText(const QString &)));
client.incomingText(QString("hello"));
return 0;
}
Agent_A *agent = qobject_cast< Agent_A* >( this->parent() ); // ?? is this is right way to do..?
if( agent != NULL )
{
qDebug() << " we are in updateTextin" << changeText; // it never get printed so I assume instance is always nULL
agent->setLineEdit( chnageText );
}
Could you please check first that parent is not NULL?
And could you please show code where you create instance of SockClient?
Of course, you can't modify text because of you set as parent to socketClient object this pointer in Server_test class, so parent to socketClient will be Server_test but no Agent_A.
So make parent Agent_A for socketClient object:
socketforClient = new SockClient(this->parent(), server->nextPendingConnection());
Or you can make some others workarounds.
One more note: you make connection to newConnection() signal at your startServer method, not constructor. So if i start server, then stop them and start again server will be connected twice to signal and slot incomingConnection() will be called twice too. So you need disconnect at from signal at stopServer() method or do connection at constructor of class or use Qt::UniqueConnection.