0

I am a newbie to QT and C++. I am stuck at a problem where I have two different classes and from B.cpp I want to access a variable of A.cpp. Using debug messages I have seen that the code hits in the setter function but it never sets the value of Textbrowser.

Here is the code of main.cpp.

#include <QApplication>
#include "window.h"
#include "socket.h"

int main(int argc, char **argv)
{
 QApplication app (argc, argv);
 Window *window = new Window();
 Socket *socket = new Socket();

 window->setStyleSheet("background-color: rgb(226, 226, 226);");
 window->showFullScreen();

 return app.exec();
}

Here is window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>

class QPushButton;
class QTextBrowser;
class QString;

class Window : public QWidget
{
    Q_OBJECT

public:
    explicit Window(QWidget *parent = 0);

    QPushButton *helloButton;
    QPushButton *exitButton;
    QPushButton *resetButton;
    QTextBrowser *clientMsgWindow;

public slots: 
    void reset();
    void setClientWindow(QString str);
};   
#endif // WINDOW_H

Here is Window.cpp

#include "window.h"
#include <QPushButton>
#include <QTextBrowser>
#include <QDebug>
#include <QString>

Window::Window(QWidget *parent) : QWidget(parent)
{
    /****************** Hello BUTTON ********************/
    helloButton = new QPushButton(this);
    helloButton->setIconSize(QSize(145, 145));
    helloButton->setGeometry(15, 160, 145, 145);
    helloButton->setText("Hello World");

   /******************reset BUTTON ********************/
    resetButton = new QPushButton(this);
    resetButton->setIconSize(QSize(145, 145));
    resetButton->setGeometry(15, 160, 145, 145);
    resetButton->setText("Click to Reset");

    /************* EXIT BUTTON *********************/
    exitButton = new QPushButton(this);
    exitButton->setIcon(QIcon(":/new/prefix1/images/exit.png"));
    exitButton->setIconSize(QSize(145, 145));
    exitButton->setGeometry(635, 10, 145, 145);
    //exitButton->setStyleSheet("background-color: rgb(236, 236, 236);");
    // Signal and slot for EXIT button
    qDebug() << connect(exitButton, SIGNAL (clicked()), this, SLOT (close()));

    /*************** TEXT BROWSER *********************/
    clientMsgWindow = new QTextBrowser(this);
    clientMsgWindow->setMinimumSize(QSize(0,0));
    clientMsgWindow->setMaximumSize(QSize(10000,10000));
    clientMsgWindow->setGeometry(175, 50, 440, 420);
    clientMSgWindow->setStyleSheet("background-color: rgb(236, 236, 236);");
    }

    void Window::setClientWindow(QString Str)
    {
        qDebug() << "Hit in Set client window to set Text";
        qDebug() << Str;
        clientMsgWindow->setText("This is the message from client");
        clientMsgWindow->setText(Str);
        qDebug() << "Setting text done";
     }

/**** Slot to reset the text browser **********/
void Window::reset()
{
    qDebug() << "Process in Reset Window";
    clientMsgWindow->clear();

}

Here is the socket.h

#ifndef SOCKET_H
#define SOCKET_H

#include <QObject>
#include <QDebug>
#include <QTcpServer>
#include <QTcpSocket>

class QTextBrowser;

class Socket : public QObject
{
    Q_OBJECT
public:
    explicit Socket(QObject *parent = 0);
    void setWindow(Window *w);
signals:

public slots:
    void newConnection();

private:
        QTcpServer *server;
        Window *window;
};

#endif // SOCKET_H

Here is the socket.cpp

#include "socket.h"
#include "window.h"
#include <QWidget>
#include <QString>

Socket::Socket(QObject *parent):
    QObject(parent)
{
    server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()), this, SLOT(newConnection()));  
    if(!server->listen(QHostAddress::QHostAddress("192.168.2.1"), 2793)){
        qDebug() << "SERVER NOT STARTED";
    }
    else{
        qDebug() << "SERVER STARTED";
    }
}
void Socket::setWindow(Window *w)
{
    this->window = w;
}
void Socket::newConnection()
{
    QString clientMsg ;
    QTcpSocket *socket= server->nextPendingConnection();
    socket->write("Server Running on 192.168.2.1");
    socket->flush();
    socket->waitForBytesWritten();

    // Recieve the data from Client
    socket->waitForReadyRead();
    qDebug() << (clientMsg = socket->readAll());

    // Set the Textbrowser clientMsgWindow
    this->window->setClientWindow(clientMsg);
} 

The GUI terminates each time client sends a message.

newbie
  • 64
  • 3

3 Answers3

0

Instead of creating a new Window instance for every single connection, you should have a single instance. You can make it a singleton, or make it a member of Socket with a setWindow() method, like this:

#ifndef SOCKET_H
#define SOCKET_H

#include <QObject>
#include <QDebug>
#include <QTcpServer>
#include <QTcpSocket>

class QTextBrowser;

class Socket : public QObject
{
    Q_OBJECT
public:
    explicit Socket(QObject *parent = 0);
    void setWindow(Window *w);
signals:

public slots:
    void newConnection();

private:
        QTcpServer *server;
        Window *window;
};

#endif // SOCKET_H

You can even add the window parameter to the constructor, so that you are forced to always set it.

Marc Coll
  • 95
  • 5
  • If I use the above code main gui window destroy's when I run client code. Here is debug message `true SERVER STARTED "Clinet : connected to server" Hit in Set client window to set Text "Clinet : connected to server" Process killed by signal` – newbie May 16 '17 at 08:41
  • Basically, you just need to pass the Window pointer you created in the main function to the socket object in some way. The easiet one is to use a setWindow() method, which should only set the window attribute of the socket ({ this->window = w; }). And then, in the newConnection slot, just use this: this->window->setclientWindow(clientMsg); – Marc Coll May 16 '17 at 12:36
  • how about achieving this using Signal and slot? I got the code compiled but at run time I get error in debug that `Object::connect: No such slot Socket::Window::setClientWindow`. Almost there can you help me out in this??? I have updated the code – newbie May 16 '17 at 12:41
  • Try with QObject::connect(socket, SIGNAL(readyRead()), this->window, SLOT(setClientWindow())) ; – Marc Coll May 16 '17 at 12:57
  • Nope, this throws an error in compilation as `class socket has no member named window` By reading the message, I think here `this` reffers to the present class not the window. Also if I connect in main.cpp as this `qDebug() << QObject::connect(&socket , SIGNAL(readyRead()), &window, SLOT(setClientWindow())) ; ` then i get error as No such signal as socket :: readyRead() – newbie May 16 '17 at 13:19
  • If you followed my instructions, class Socket should have a window object. Perhaps you named it differently. this->window means: the attribute named "window" inside of the current object. – Marc Coll May 16 '17 at 13:27
  • Sorry for that, I missed that line. I was able to connect but again the same problem, Process gets killed as soon as I send message from client – newbie May 16 '17 at 13:34
  • Are you using the setWindow() method? – Marc Coll May 16 '17 at 13:38
  • No, using signal and slot. – newbie May 16 '17 at 13:42
  • Signals and slots have nothing to do with this! You have to set the Window pointer inside of the Socket by using the setWindow method. Otherwise, you are calling an uninitialized pointer, which will most likely crash your program. – Marc Coll May 16 '17 at 13:46
  • I am editing the full code as per your suggestion. I tried to follow your steps, confused a little bit. Kindly have a look. – newbie May 16 '17 at 14:13
  • It's not enough to define the method, you are supposed to call it from your main function. Otherwise, the socket will never know about your Window. – Marc Coll May 16 '17 at 14:24
  • Got it, thankyou so much,.... You solved my problem. But more over that. I want to learn C++ and QT, can you guide me how I should cover this ? – newbie May 16 '17 at 14:30
  • Add this: socket->setWindow(window); in the 4th line of your main function, right after creating the socket object, and see what happens. – Marc Coll May 16 '17 at 14:31
  • There are many tutorials online, but I can't really recommend you one in particular. I'm sure you can find recommendations here at Stack Overflow. In any case, my advice is to learn C++ first, and then Qt. If you try to learn them both at the same time, it might be confusing. – Marc Coll May 16 '17 at 14:33
  • I know C, for C++. can you recommend something ?? Mostly I have to focus on classes object. – newbie May 16 '17 at 14:35
  • Try with this thread: [http://stackoverflow.com/questions/1421668](http://stackoverflow.com/questions/1421668) – Marc Coll May 16 '17 at 14:41
0

Your design seems to be flawed. When you call

Window* pWindow = new Window();
pWindow->setclientWindow(clientMsg);

in your newConnection method you are creating a new window object and set the text there. However, this is not the same window object you created in your main method, so obviously you won't see the text there. In fact the object you create in the newConnection method is lost forever, since you don't save the pointer anywhere, which will also lead to leaked memory since you can't clean it up. You have to connect your two objects somehow by storing a pointer to the other.

Sebastian Stern
  • 632
  • 4
  • 15
  • can I use signal and slot mechanism in this to connect them ?? – newbie May 16 '17 at 08:51
  • Not sure what those macros do, what I meant is something like Marcs answer, where you store the pointer of the window in the socket (or the other way around). – Sebastian Stern May 16 '17 at 09:06
  • It crashes the GUI window, If I follow Marcs answer. I understood few things what you said that I am creating a new Window object each time there is a new connection. Confused on what to do and how to do. Can't I use a Signal slot mechanism like `connect((socket, SIGNAL (readyRead)), this, SLOT(setClientWindow));` to make it work ??? – newbie May 16 '17 at 09:16
  • I never used Qt before, so I'm not sure about that. But from a brief glimpse into the conecpt, yes you could also use that mechanism to make it work. It's probably more idiomatic than storing the raw pointer. – Sebastian Stern May 16 '17 at 09:32
0
Object::connect: No such slot Socket::Window::setClientWindow()

This error shows that your signal slot parameters are incompatible because setClientWindow takes a QString parameter, and void signal readReady is emitted.

Edit: Following your comment, I see you need to understand basic concepts of signal/slots.

Your connection should be like:

QObject::connect(socket, SIGNAL(readyRead()), window, SLOT(setClientWindow()))

but you don't have a window object to which you can connect socket. You need to refactor your code because it has many design issues.

iM71
  • 301
  • 2
  • 6