Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QLabel won't update from Slot
Forum Updated to NodeBB v4.3 + New Features

QLabel won't update from Slot

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 3 Posters 1.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    rahulb1218
    wrote on last edited by rahulb1218
    #1

    Forgive me, I am a complete beginner. I am trying to learn how to receive a message from a client and display on the server ui. I have that figured out. My problem is when trying to update the UI with that message. For right now, I am not worrying about the exact message, but just having the UI update when a message is received. However, my UI will not update. Here is the relevant code:

    Line that calls the slot from another class:

    connect(socket, SIGNAL(readyRead()), &mw, SLOT(fillText()));
    

    mw is a MainWindow Object

    mainwindow.cpp:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    int num;
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        
        itemLabel->setText("Label Created");
    
        ui->gridLayout->addWidget(itemLabel, 0, 0);
        
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    void MainWindow::fillText()
    {
        qDebug() << "inside fillText function ";
        num = arc4random();
        itemLabel->setText("updated number to show SLOT is working: " + QString::number(num));
        qDebug() << "item Label's text: " + itemLabel->text();
        this->setStyleSheet("background-color: green;");
        QWidget::repaint();//was a suggestion I saw, but does not work
        
    }
    

    mainwindow.h:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QLabel>
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
        QLabel *itemLabel = new QLabel();
        QLabel *label2;
    
    private slots:
        void fillText();
        void signalTest();
    private slots:
        
    signals:
        
    
    private:
        Ui::MainWindow *ui;
    };
    #endif // MAINWINDOW_H
    

    Thanks for all the help!!

    quick edit: I know textFill() is called because

    qDebug() << "inside fillText function ";
    

    works, and

    qDebug() << "item Label's text: " + itemLabel->text();
    

    actually prints out "item Label's text: updated number to show SLOT is working: (random num) every time I send a message from my client.

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by mrjj
      #2

      Hi
      in this line
      connect(socket, SIGNAL(readyRead()), &mw, SLOT(fillText()));
      what is mw ?

      anyway, it sounds like the slot works so the connection is ok.

      so which part is not updating?
      itemLabel->setText sounds like its updating as you see the random number ?

      Ahh you mean how to read the actual massage from socket and pass that along ?

      R 1 Reply Last reply
      0
      • mrjjM mrjj

        Hi
        in this line
        connect(socket, SIGNAL(readyRead()), &mw, SLOT(fillText()));
        what is mw ?

        anyway, it sounds like the slot works so the connection is ok.

        so which part is not updating?
        itemLabel->setText sounds like its updating as you see the random number ?

        Ahh you mean how to read the actual massage from socket and pass that along ?

        R Offline
        R Offline
        rahulb1218
        wrote on last edited by
        #3

        @mrjj Hello, mw is a MainWindow object I initialized in the header file of this other class.

        So, qDebug tells me that the label's text value is indeed updating. However, in the actual GUI window, the the text for itemLabel remains "Label Created," which according to this line:

        qDebug() << "item Label's text: " + itemLabel->text();

        is not the case.

        No, I have not yet tried to work on the actual message, just trying to get the GUI to update when a message is received is my worry for now.

        mrjjM 1 Reply Last reply
        0
        • R rahulb1218

          @mrjj Hello, mw is a MainWindow object I initialized in the header file of this other class.

          So, qDebug tells me that the label's text value is indeed updating. However, in the actual GUI window, the the text for itemLabel remains "Label Created," which according to this line:

          qDebug() << "item Label's text: " + itemLabel->text();

          is not the case.

          No, I have not yet tried to work on the actual message, just trying to get the GUI to update when a message is received is my worry for now.

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by mrjj
          #4

          @rahulb1218

          Hi
          But is this the classic gotcha then?

          You already have one mainwindow, you look at but then create a
          new one called mw (which you don't call show on) and you connect to that
          but its not the one that is actually showing ?

          To fix this , you can connect where you create the "otheclass" that has the socket

          like if you create it in Mainwindow

          TheOTherclass * other = new TheOTherclass(this)
          connect(other->socket, SIGNAL(readyRead()), this, SLOT(fillText()));

          R 1 Reply Last reply
          2
          • mrjjM mrjj

            @rahulb1218

            Hi
            But is this the classic gotcha then?

            You already have one mainwindow, you look at but then create a
            new one called mw (which you don't call show on) and you connect to that
            but its not the one that is actually showing ?

            To fix this , you can connect where you create the "otheclass" that has the socket

            like if you create it in Mainwindow

            TheOTherclass * other = new TheOTherclass(this)
            connect(other->socket, SIGNAL(readyRead()), this, SLOT(fillText()));

            R Offline
            R Offline
            rahulb1218
            wrote on last edited by
            #5

            @mrjj ohhhhh I see what I did now.
            How would I write this line since my other class has a qintptr argument:
            qDebug() << "item Label's text: " + itemLabel->text();

            mythread.h:

            #ifndef MYTHREAD_H
            #define MYTHREAD_H
            #include <QThread>
            #include <QTcpSocket>
            #include <QObject>
            #include "mainwindow.h"
            
            class MyThread : public QThread
            {
                Q_OBJECT
            public:
                explicit MyThread(qintptr ID, QObject *parent = 0);
                void run();
            signals:
                void error(QTcpSocket::SocketError socketerror);
            
            public slots:
                void readyRead();
                void disconnected();
            private:
                QTcpSocket *socket;
                qintptr socketDescriptor;
                MainWindow mw;
            };
            
            #endif // MYTHREAD_H
            
            

            mythread.cpp(contains old connect code, but I will take it out and put connect in MainWindow):

            #include "mythread.h"
            
            
            MyThread::MyThread(qintptr ID, QObject *parent) :
                QThread(parent)
            {
                this->socketDescriptor = ID;
            }
            
            void MyThread::run()
            {
                qDebug() << "Thread started";
                socket = new QTcpSocket();
            
                if(!socket->setSocketDescriptor(this->socketDescriptor))
                    {
                        // something's wrong, we just emit a signal
                        emit error(socket->error());
                        return;
                    }
                connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
                connect(socket, SIGNAL(readyRead()), &mw, SLOT(fillText()));
                connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
                qDebug() << socketDescriptor << " Client connected";
                exec();
            }
            void MyThread::readyRead()
            {
                QByteArray Data = socket->readAll();
                qDebug() << socketDescriptor << " Data in: " << Data;
                socket->write("Data reply: " + Data);
            }
            void MyThread::disconnected()
            {
                qDebug() << socketDescriptor << " Disconnected";
                socket->deleteLater();
                exit(0);
            }
            
            

            thank you so much!!

            1 Reply Last reply
            0
            • mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by mrjj
              #6

              Hi
              What about making a new signal like the
              void error(QTcpSocket::SocketError socketerror);

              but then instead

              void DataReady(QString text );

              and then in
              void MyThread::readyRead()
              {
              QByteArray Data = socket->readAll();
              qDebug() << socketDescriptor << " Data in: " << Data;
              socket->write("Data reply: " + Data);
              emit DataReady(QString(Data)); // we got something to show in MainWindow
              }

              and then in Mainwindow (the real one) you connect the new signal DataReady
              to some slot and there you do the itemLabel->text(); thing as MainWindow has that
              Qlabel and it's NOT allowed to fiddle with Widgets across threads and MyThread is such a beast so
              you should not call setText or any function on Widgets that are in MainWindow.

              Also, Do you really need a new Thread ?
              QTcpSocket is already async and will send signal when to read new data so
              it won't block the main GUI thread.
              If you later plan on doing heavy calculation/processing on the incoming data it's fine but
              just had to ask :)

              R 1 Reply Last reply
              3
              • mrjjM mrjj

                Hi
                What about making a new signal like the
                void error(QTcpSocket::SocketError socketerror);

                but then instead

                void DataReady(QString text );

                and then in
                void MyThread::readyRead()
                {
                QByteArray Data = socket->readAll();
                qDebug() << socketDescriptor << " Data in: " << Data;
                socket->write("Data reply: " + Data);
                emit DataReady(QString(Data)); // we got something to show in MainWindow
                }

                and then in Mainwindow (the real one) you connect the new signal DataReady
                to some slot and there you do the itemLabel->text(); thing as MainWindow has that
                Qlabel and it's NOT allowed to fiddle with Widgets across threads and MyThread is such a beast so
                you should not call setText or any function on Widgets that are in MainWindow.

                Also, Do you really need a new Thread ?
                QTcpSocket is already async and will send signal when to read new data so
                it won't block the main GUI thread.
                If you later plan on doing heavy calculation/processing on the incoming data it's fine but
                just had to ask :)

                R Offline
                R Offline
                rahulb1218
                wrote on last edited by rahulb1218
                #7

                @mrjj oh yes that would work, and I could probably manage with one thread but I will keep it like this for now and optimize later.
                So in MainWindow, I would do this:

                MyThread * other = new MyThread(this)
                connect(other, SIGNAL(dataReceived(QString Data??)), this, SLOT(fillText()));

                But how would I initialize “*other” since has a required arg? That is my confusion.

                I need other so I can specify the sender object.

                or do you mean DataReady signal should belong to MainWindow?

                My first QT and c++ project, sorry.

                mrjjM 1 Reply Last reply
                0
                • R rahulb1218

                  @mrjj oh yes that would work, and I could probably manage with one thread but I will keep it like this for now and optimize later.
                  So in MainWindow, I would do this:

                  MyThread * other = new MyThread(this)
                  connect(other, SIGNAL(dataReceived(QString Data??)), this, SLOT(fillText()));

                  But how would I initialize “*other” since has a required arg? That is my confusion.

                  I need other so I can specify the sender object.

                  or do you mean DataReady signal should belong to MainWindow?

                  My first QT and c++ project, sorry.

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by mrjj
                  #8

                  @rahulb1218

                  Hi
                  Yes but one never shows the param name in the connect so

                  MyThread * other = new MyThread(this)
                  connect(other, SIGNAL(dataReceived(QString)), this, SLOT(fillText()));

                  ( I assume that dataReceived is your name for DataReady example)

                  and you should change the filltext from

                  void fillText()
                  ->
                  void fillText(QString data);

                  As in - add new parameter to your slot, to use the data.

                  • But how would I initialize “*other” since has a required arg? That is my confusion.

                  You mean the connect or the
                  MyThread * other = new MyThread(this)
                  part ?

                  • My first QT and c++ project, sorry.
                    Then it goes pretty well I must say :)

                  When you feel for it, you should have a look at the new way to connect
                  https://wiki.qt.io/New_Signal_Slot_Syntax

                  R 1 Reply Last reply
                  1
                  • mrjjM mrjj

                    @rahulb1218

                    Hi
                    Yes but one never shows the param name in the connect so

                    MyThread * other = new MyThread(this)
                    connect(other, SIGNAL(dataReceived(QString)), this, SLOT(fillText()));

                    ( I assume that dataReceived is your name for DataReady example)

                    and you should change the filltext from

                    void fillText()
                    ->
                    void fillText(QString data);

                    As in - add new parameter to your slot, to use the data.

                    • But how would I initialize “*other” since has a required arg? That is my confusion.

                    You mean the connect or the
                    MyThread * other = new MyThread(this)
                    part ?

                    • My first QT and c++ project, sorry.
                      Then it goes pretty well I must say :)

                    When you feel for it, you should have a look at the new way to connect
                    https://wiki.qt.io/New_Signal_Slot_Syntax

                    R Offline
                    R Offline
                    rahulb1218
                    wrote on last edited by rahulb1218
                    #9

                    @mrjj

                    MyThread * other = new MyThread(this)
                    When I use this, I get the "no matching constructor for initialization of "MyThread." I think this is because the param needs to be of type qintptr, right?

                    So I tried something. I tried to grab the MyThread object that is initialized in my server files header. I will attach. I used extern and added this line to my mainwindow.cpp. However, this would give me linker error when compiling.

                    myserver.h:

                    #ifndef MYSERVER_H
                    #define MYSERVER_H
                    #include <QTcpServer>
                    
                    class MyServer : public QTcpServer
                    {
                        Q_OBJECT
                    public:
                        MyServer(QObject *parent = 0);
                        void startServer();
                    protected:
                        void incomingConnection(qintptr socketDescriptor);
                    };
                    
                    #endif // MYSERVER_H
                    
                    

                    myserver.cpp:

                    #include "myserver.h"
                    #include "mythread.h"
                    
                    MyServer::MyServer(QObject *parent) :
                        QTcpServer(parent)
                    {
                    
                    }
                    void MyServer::startServer()
                    {
                        int port = 1234;
                        if(!this->listen(QHostAddress::Any, port))
                            {
                                qDebug() << "Could not start server";
                            }
                            else
                            {
                                qDebug() << "Listening to port " << port << "...";
                            }
                    }
                    void MyServer::incomingConnection(qintptr socketDescriptor)
                    {
                        // We have a new connection
                        qDebug() << socketDescriptor << " Connecting...";
                    
                        MyThread *threadly = new MyThread(socketDescriptor, this);
                    
                        // connect signal/slot
                        // once a thread is not needed, it will be beleted later
                        connect(threadly, SIGNAL(finished()), threadly, SLOT(deleteLater()));
                    
                        threadly->start();
                    }
                    
                    

                    In mainwindow.cpp, I added

                    extern const MyThread* threadly;
                    

                    and

                    connect(threadly, SIGNAL(dataSignal()), this, SLOT(fillText()));
                    

                    It would give a linker error at this line. I read online that I must #include mainwindow.moc, but QT could not find that file.

                    However, if you believe that this is the wrong way to tackle this, and instead initialize another MyThread object in mainwindow, I will do that instead, but the correct way as using (this) as the param does not work for me.

                    And again, thank you so much for the help!

                    PS: the error detail for using MyThread(this) is: no matching constructor for initialization of 'MyThread'
                    note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'MainWindow *' to 'const MyThread' for 1st argument
                    note: candidate constructor not viable: no known conversion from 'MainWindow *' to 'qintptr' (aka 'long long') for 1st argument

                    JonBJ 1 Reply Last reply
                    0
                    • R rahulb1218

                      @mrjj

                      MyThread * other = new MyThread(this)
                      When I use this, I get the "no matching constructor for initialization of "MyThread." I think this is because the param needs to be of type qintptr, right?

                      So I tried something. I tried to grab the MyThread object that is initialized in my server files header. I will attach. I used extern and added this line to my mainwindow.cpp. However, this would give me linker error when compiling.

                      myserver.h:

                      #ifndef MYSERVER_H
                      #define MYSERVER_H
                      #include <QTcpServer>
                      
                      class MyServer : public QTcpServer
                      {
                          Q_OBJECT
                      public:
                          MyServer(QObject *parent = 0);
                          void startServer();
                      protected:
                          void incomingConnection(qintptr socketDescriptor);
                      };
                      
                      #endif // MYSERVER_H
                      
                      

                      myserver.cpp:

                      #include "myserver.h"
                      #include "mythread.h"
                      
                      MyServer::MyServer(QObject *parent) :
                          QTcpServer(parent)
                      {
                      
                      }
                      void MyServer::startServer()
                      {
                          int port = 1234;
                          if(!this->listen(QHostAddress::Any, port))
                              {
                                  qDebug() << "Could not start server";
                              }
                              else
                              {
                                  qDebug() << "Listening to port " << port << "...";
                              }
                      }
                      void MyServer::incomingConnection(qintptr socketDescriptor)
                      {
                          // We have a new connection
                          qDebug() << socketDescriptor << " Connecting...";
                      
                          MyThread *threadly = new MyThread(socketDescriptor, this);
                      
                          // connect signal/slot
                          // once a thread is not needed, it will be beleted later
                          connect(threadly, SIGNAL(finished()), threadly, SLOT(deleteLater()));
                      
                          threadly->start();
                      }
                      
                      

                      In mainwindow.cpp, I added

                      extern const MyThread* threadly;
                      

                      and

                      connect(threadly, SIGNAL(dataSignal()), this, SLOT(fillText()));
                      

                      It would give a linker error at this line. I read online that I must #include mainwindow.moc, but QT could not find that file.

                      However, if you believe that this is the wrong way to tackle this, and instead initialize another MyThread object in mainwindow, I will do that instead, but the correct way as using (this) as the param does not work for me.

                      And again, thank you so much for the help!

                      PS: the error detail for using MyThread(this) is: no matching constructor for initialization of 'MyThread'
                      note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'MainWindow *' to 'const MyThread' for 1st argument
                      note: candidate constructor not viable: no known conversion from 'MainWindow *' to 'qintptr' (aka 'long long') for 1st argument

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #10

                      @rahulb1218
                      You have said:

                      My first QT and c++ project, sorry.

                      @mrjj oh yes that would work, and I could probably manage with one thread but I will keep it like this for now and optimize later.

                      Why in the world are you soldiering on using threads? They are probably the single hardest part of Qt (or other toolkit) to get right, and you are now having problems with them. I would not dream of using threads if I were new to C++ & Qt.

                      I don't know what you are trying to achieve but these Fortune examples do QTcpSocket without any threads:

                      • Fortune Client Example
                      • Fortune Server Example

                      If you do want (really need!) to use threads have you had a look at:

                      • Threaded Fortune Server Example
                      R 1 Reply Last reply
                      4
                      • JonBJ JonB

                        @rahulb1218
                        You have said:

                        My first QT and c++ project, sorry.

                        @mrjj oh yes that would work, and I could probably manage with one thread but I will keep it like this for now and optimize later.

                        Why in the world are you soldiering on using threads? They are probably the single hardest part of Qt (or other toolkit) to get right, and you are now having problems with them. I would not dream of using threads if I were new to C++ & Qt.

                        I don't know what you are trying to achieve but these Fortune examples do QTcpSocket without any threads:

                        • Fortune Client Example
                        • Fortune Server Example

                        If you do want (really need!) to use threads have you had a look at:

                        • Threaded Fortune Server Example
                        R Offline
                        R Offline
                        rahulb1218
                        wrote on last edited by
                        #11

                        @JonB

                        I'm working on a project where I need to able to send a string from one device to another. So, the first thing I did was look up was examples of one script talking to another. One of the first ones I found used threads. I will however try this, thank you!

                        JonBJ 1 Reply Last reply
                        0
                        • R rahulb1218

                          @JonB

                          I'm working on a project where I need to able to send a string from one device to another. So, the first thing I did was look up was examples of one script talking to another. One of the first ones I found used threads. I will however try this, thank you!

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by JonB
                          #12

                          @rahulb1218
                          Depends whether these "scripts" were for Qt or not. Qt's TCP/socket code is inherently asynchronous, whereas other examples/toolkits are likely to be synchronous and so require threads.

                          I did not say using threads was necessarily wrong (depends exactly what you have to do in your proposed thread). What I did say is that if I were new to both Qt & C++ I would not choose to use threading if I could possibly help it! :)

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved