1

I have been new to the Qt environment. I recently started with a QtCreator project for a simple chat application (QMainWindow). I have nearly completed the project but stuck with the SIGNAL/SLOT problem.

Let me explain my problem in brief :

Due to the length of the code I am not able to paste it here.

  1. I have two classes MainWindow and NetworkFile.
  2. The function newServerConn() in NetworkFile connects the signal readyRead() to the slot readFromClient().
  3. The string returned by client is stored in a QString in readFromClient() SLOT.

Problem:

I have to return the QString in the slot to the newServerConn() function and from there to a function in MainWindow class because only then I would be able to print the string to the plainLineEdit widget pointed by the ui object.

Question 1: How can I return a value from the slot?

Question 2: Or is there any way I could get a copy of the ui instance in the NetworkFile class so that I could use the widgets from there?

Thanks.

Panther Coder
  • 1,058
  • 1
  • 16
  • 43
  • "Due to the length of the code I am not able to paste it here." In almost no circumstances you should be pasting such code here *anyway*. Your job as a question asker is to provide a minimum example that reproduces the issue. It doesn't happen automatically, you usually have to create a branch in your repository to minimize the problem, and then minimize it to a single file, and only the post it as a part of the question. There are very few problems that don't reproduce in under a 150 lines considered reasonable to include in a question. – Kuba hasn't forgotten Monica May 22 '17 at 13:35

2 Answers2

1

As from the documentation:

Signals [...] can never have return types (i.e. use void).

Therefore slot return types are useless when invoked through a signal (even though you can still use them when you invoke a slot directly, ie if it's a member function).

That being said, you can capture ui or even better plainLineEdit by reference or by address in your slot (ie if it's a lambda) and set correctly the string from there.

skypjack
  • 49,335
  • 19
  • 95
  • 187
1

I would just emit the data as a signal and wire up the connection between that new signal and a slot where you add then string to your ui.

A quick self-contained example (which btw. "Due to the length of the code I am not able to paste it here." is just an excuse, you can pretty much always cut down your relevant code)

Header:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTextEdit>

class NetworkFile;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow(){}

public slots:
    void addText(QString str)
    {
        edit->append(str);
    }

private:
    QTextEdit* edit;
    NetworkFile* net;
};

class NetworkFile : public QObject
{
    Q_OBJECT

public:
    NetworkFile(QObject *parent = 0):
        QObject(parent)
    {
        connect(&server, &QTcpServer::newConnection,
                this, &NetworkFile::newConnection);
        //TODO: check return value
        server.listen(QHostAddress::Any,16001);
    }

signals:
    void dataRead(QString);

public slots:
    void newConnection(){
        //TODO: wire up socket disconnect with deleteLater, also check for null
        QTcpSocket* socket = server.nextPendingConnection();
        connect(socket, &QTcpSocket::readyRead,
                this, &NetworkFile::dataAvailable);
    }

    void dataAvailable(){
        //HACK: only for brevity, create a connection wrapper that contains the socket in real code
        QTcpSocket* source = (QTcpSocket*)sender();

        auto bytes = source->readAll();
        if(bytes.size())
        {
            emit dataRead(QString(bytes));
        }
    }

private:
    QTcpServer server;
};

#endif // MAINWINDOW_H

cpp file

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

MainWindow::MainWindow(QWidget *parent ):
    QMainWindow(parent)
{
    edit = new QTextEdit(this);
    net = new NetworkFile(this);

    connect(net, &NetworkFile::dataRead,
            this, &MainWindow::addText );
    setCentralWidget(edit);
}

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

    return a.exec();
}
PeterT
  • 7,981
  • 1
  • 26
  • 34
  • Thanks a lot. But, where does the control of the program go after emit signal? I mean where will I receive the string? – Panther Coder May 20 '17 at 18:04
  • 1
    `connect(net, &NetworkFile::dataRead, this, &MainWindow::addText );` This makes it so that when you call `dataRead` on this specific instance it will call `addText` (depending on the circumstances directly or queued in the eventloop). If you are using Qt you should probably familiarize yourself with the signal/slot system. – PeterT May 20 '17 at 18:08
  • 1
    btw. `connect(net, &NetworkFile::dataRead, this, &MainWindow::addText );` is the same as `connect(net, SIGNAL(dataRead), this, SLOT(addText) );` but with the added benefit of type-checking at compile-time. – PeterT May 20 '17 at 18:11
  • So, through signals we can call a function in another class? – Panther Coder May 20 '17 at 18:12
  • 1
    @PantherCoder spoonfeeding you how Qt works seems like a poor use of time, considering how great their documentation is. [Take a look](http://doc.qt.io/qt-5.8/signalsandslots.html) – PeterT May 20 '17 at 18:14
  • ouch...Thanks anyway. – Panther Coder May 20 '17 at 18:18