Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Send data packets to multiple windows/widgets
Forum Updated to NodeBB v4.3 + New Features

Send data packets to multiple windows/widgets

Scheduled Pinned Locked Moved Solved Qt for Python
12 Posts 4 Posters 2.2k Views 2 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.
  • T Offline
    T Offline
    tilz0R
    wrote on last edited by
    #1

    I have one QMainWindow that opens DLL and receives data from it.
    This QMainWindow has different other windows opened, and holds its reference to it.

    I'd like to make a generic "driver" where each new window can subscribe to receive packets coming from DLL. Right now, when DLL packet arrives, it gets written to queue, which is later processed in QTimer callback, every 50ms at the moment.

    What is the correct and suggested way from Qt to achieve such task?

    I see one option with signals:

    • QMainWindow creates signal object that is emitted on every DLL message
    • New window, when created, receives pointer to parent, and can subscribe to signal. Signal will therefore have multiple connections
    • Use closeEvent to disconnect from signal

    Is this the right way?

    JonBJ M 2 Replies Last reply
    0
    • T tilz0R

      I have one QMainWindow that opens DLL and receives data from it.
      This QMainWindow has different other windows opened, and holds its reference to it.

      I'd like to make a generic "driver" where each new window can subscribe to receive packets coming from DLL. Right now, when DLL packet arrives, it gets written to queue, which is later processed in QTimer callback, every 50ms at the moment.

      What is the correct and suggested way from Qt to achieve such task?

      I see one option with signals:

      • QMainWindow creates signal object that is emitted on every DLL message
      • New window, when created, receives pointer to parent, and can subscribe to signal. Signal will therefore have multiple connections
      • Use closeEvent to disconnect from signal

      Is this the right way?

      M Offline
      M Offline
      mpergand
      wrote on last edited by mpergand
      #11

      @tilz0R said in Send data packets to multiple windows/widgets:

      I have one QMainWindow that opens DLL and receives data from it.
      This QMainWindow has different other windows opened, and holds its reference to it.

      If mainWindow has a ref to child windows, why not send data directly to them ?
      To manage child windows deleting, you can use QPointer as it will be set to null.
      Here a standalone example:

      class ChildWindow : public QWidget
      {
          public:
              ChildWindow(QWidget* parent=nullptr) : QWidget(parent)
                  {
                      setAttribute(Qt::WA_DeleteOnClose);
                  }
      
              void setData(const QByteArray& data)
                  {
                  qDebug()<<objectName()<<data;
                  }
      };
      
      class MainWin : public QMainWindow
      {
          public:
              MainWin() : QMainWindow()
                  {
                  // use a timer to simulate incoming data
                  QTimer* timer=new QTimer(this);
                  connect(timer, &QTimer::timeout,this,[this]()
                  {
                      static int i=0;
                      i++;
      
                      auto it = childWindows.begin();
      
                      while (it != childWindows.end())
                          {
                          if (*it==nullptr)   // removed from the vector if child win deleted/closed
                              it = childWindows.erase(it);
                          else
                              {
                              (**it).setData(QString("Data %1").arg(i).toLatin1());
                              ++it;
                              }
                          }
                  });
                  
                  timer->start(1000);
      
                  for(int i=0; i<3; i++)
                      {
                      ChildWindow* w=new ChildWindow;
                      w->setObjectName(QString("Child %1").arg(i+1));
                      w->setWindowTitle(w->objectName());
                      w->show();
                      childWindows<<w;
                      }
      
                  }
      
          private:
              QVector<QPointer<ChildWindow> > childWindows;
      
      };
      
      int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
      
      MainWin win;
      win.setWindowTitle("Main WIndow");
      win.show();
          return app.exec();
      }
      
      T 1 Reply Last reply
      0
      • T tilz0R

        I have one QMainWindow that opens DLL and receives data from it.
        This QMainWindow has different other windows opened, and holds its reference to it.

        I'd like to make a generic "driver" where each new window can subscribe to receive packets coming from DLL. Right now, when DLL packet arrives, it gets written to queue, which is later processed in QTimer callback, every 50ms at the moment.

        What is the correct and suggested way from Qt to achieve such task?

        I see one option with signals:

        • QMainWindow creates signal object that is emitted on every DLL message
        • New window, when created, receives pointer to parent, and can subscribe to signal. Signal will therefore have multiple connections
        • Use closeEvent to disconnect from signal

        Is this the right way?

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

        @tilz0R
        This is about how I would do it in Qt. Except I wouldn't pass a "pointer to parent [main window]" to other windows. Create an object to emit the signals rather than having it a part of the main window, other windows can place slots on it without accessing the main window.

        T 1 Reply Last reply
        1
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #3

          Hi,

          As @JonB suggests, create a controller object that manages the interaction with that dll.

          You can then have an instance of it in your main window and connect all the "sub-windows" to that controller.

          From the looks of it, none of these widgets needs to know anything about the controller. Give them a proper slot to receive the data.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1
          • JonBJ JonB

            @tilz0R
            This is about how I would do it in Qt. Except I wouldn't pass a "pointer to parent [main window]" to other windows. Create an object to emit the signals rather than having it a part of the main window, other windows can place slots on it without accessing the main window.

            T Offline
            T Offline
            tilz0R
            wrote on last edited by
            #4

            @JonB So your suggestion is to have a singleton object(that extends QObject) where each new instance who wants to receive packets, can get instance and connect to it?

            JonBJ 1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #5

              There's no need for any singleton.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • T tilz0R

                @JonB So your suggestion is to have a singleton object(that extends QObject) where each new instance who wants to receive packets, can get instance and connect to it?

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

                @tilz0R
                If you allow the main window to have the instance and connect to publicly exposed slots in the windows it creates then it can do the connects. The spawned windows do not do the connecting. That is what @SGaist is suggesting. So no need for a singleton.

                T 1 Reply Last reply
                1
                • JonBJ JonB

                  @tilz0R
                  If you allow the main window to have the instance and connect to publicly exposed slots in the windows it creates then it can do the connects. The spawned windows do not do the connecting. That is what @SGaist is suggesting. So no need for a singleton.

                  T Offline
                  T Offline
                  tilz0R
                  wrote on last edited by
                  #7

                  @JonB This will then allow to receive slots from spawn windows to the main one. Correct?

                  What about the opposite way? Is there a good example not to shoot myself to the knee?

                  JonBJ 1 Reply Last reply
                  0
                  • T tilz0R

                    @JonB This will then allow to receive slots from spawn windows to the main one. Correct?

                    What about the opposite way? Is there a good example not to shoot myself to the knee?

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

                    @tilz0R
                    Yes, main window will go

                        this->otherWindow = new OtherWindow(this);
                        connect(this->dllSignaller, &DllSignaller::packetArrived,
                                this->otherWindow, &OtherWindow::onPacketArrivedSlot);
                    

                    The "opposite way", assuming you mean the "other windows" would have to know about the main window in order to get at the DLL signaller object, is not a good design. It means they are dependent on your main window, while there is no need for them to be. The general rule is it's OK for parents to know about children but try to make children not know about parents.

                    T 1 Reply Last reply
                    1
                    • JonBJ JonB

                      @tilz0R
                      Yes, main window will go

                          this->otherWindow = new OtherWindow(this);
                          connect(this->dllSignaller, &DllSignaller::packetArrived,
                                  this->otherWindow, &OtherWindow::onPacketArrivedSlot);
                      

                      The "opposite way", assuming you mean the "other windows" would have to know about the main window in order to get at the DLL signaller object, is not a good design. It means they are dependent on your main window, while there is no need for them to be. The general rule is it's OK for parents to know about children but try to make children not know about parents.

                      T Offline
                      T Offline
                      tilz0R
                      wrote on last edited by
                      #9

                      @JonB OK - thanks makes sense in DLL direction. I suppose main window should then do the same to detect when child window is closed (but not destroyed in the memory). To disconnect sending packets there.

                      JonBJ 1 Reply Last reply
                      0
                      • T tilz0R

                        @JonB OK - thanks makes sense in DLL direction. I suppose main window should then do the same to detect when child window is closed (but not destroyed in the memory). To disconnect sending packets there.

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

                        @tilz0R
                        It could, if say you make the child emit a "closed" signal by overriding its closeEvent(). And then you'll have to attach its re-open event too.

                        Or, why does the main window actually need to detach closed child from signal? Child could equally detect it is closed and not both to do work in its slot.

                        1 Reply Last reply
                        0
                        • T tilz0R

                          I have one QMainWindow that opens DLL and receives data from it.
                          This QMainWindow has different other windows opened, and holds its reference to it.

                          I'd like to make a generic "driver" where each new window can subscribe to receive packets coming from DLL. Right now, when DLL packet arrives, it gets written to queue, which is later processed in QTimer callback, every 50ms at the moment.

                          What is the correct and suggested way from Qt to achieve such task?

                          I see one option with signals:

                          • QMainWindow creates signal object that is emitted on every DLL message
                          • New window, when created, receives pointer to parent, and can subscribe to signal. Signal will therefore have multiple connections
                          • Use closeEvent to disconnect from signal

                          Is this the right way?

                          M Offline
                          M Offline
                          mpergand
                          wrote on last edited by mpergand
                          #11

                          @tilz0R said in Send data packets to multiple windows/widgets:

                          I have one QMainWindow that opens DLL and receives data from it.
                          This QMainWindow has different other windows opened, and holds its reference to it.

                          If mainWindow has a ref to child windows, why not send data directly to them ?
                          To manage child windows deleting, you can use QPointer as it will be set to null.
                          Here a standalone example:

                          class ChildWindow : public QWidget
                          {
                              public:
                                  ChildWindow(QWidget* parent=nullptr) : QWidget(parent)
                                      {
                                          setAttribute(Qt::WA_DeleteOnClose);
                                      }
                          
                                  void setData(const QByteArray& data)
                                      {
                                      qDebug()<<objectName()<<data;
                                      }
                          };
                          
                          class MainWin : public QMainWindow
                          {
                              public:
                                  MainWin() : QMainWindow()
                                      {
                                      // use a timer to simulate incoming data
                                      QTimer* timer=new QTimer(this);
                                      connect(timer, &QTimer::timeout,this,[this]()
                                      {
                                          static int i=0;
                                          i++;
                          
                                          auto it = childWindows.begin();
                          
                                          while (it != childWindows.end())
                                              {
                                              if (*it==nullptr)   // removed from the vector if child win deleted/closed
                                                  it = childWindows.erase(it);
                                              else
                                                  {
                                                  (**it).setData(QString("Data %1").arg(i).toLatin1());
                                                  ++it;
                                                  }
                                              }
                                      });
                                      
                                      timer->start(1000);
                          
                                      for(int i=0; i<3; i++)
                                          {
                                          ChildWindow* w=new ChildWindow;
                                          w->setObjectName(QString("Child %1").arg(i+1));
                                          w->setWindowTitle(w->objectName());
                                          w->show();
                                          childWindows<<w;
                                          }
                          
                                      }
                          
                              private:
                                  QVector<QPointer<ChildWindow> > childWindows;
                          
                          };
                          
                          int main(int argc, char *argv[])
                          {
                              QApplication app(argc, argv);
                          
                          MainWin win;
                          win.setWindowTitle("Main WIndow");
                          win.show();
                              return app.exec();
                          }
                          
                          T 1 Reply Last reply
                          0
                          • M mpergand

                            @tilz0R said in Send data packets to multiple windows/widgets:

                            I have one QMainWindow that opens DLL and receives data from it.
                            This QMainWindow has different other windows opened, and holds its reference to it.

                            If mainWindow has a ref to child windows, why not send data directly to them ?
                            To manage child windows deleting, you can use QPointer as it will be set to null.
                            Here a standalone example:

                            class ChildWindow : public QWidget
                            {
                                public:
                                    ChildWindow(QWidget* parent=nullptr) : QWidget(parent)
                                        {
                                            setAttribute(Qt::WA_DeleteOnClose);
                                        }
                            
                                    void setData(const QByteArray& data)
                                        {
                                        qDebug()<<objectName()<<data;
                                        }
                            };
                            
                            class MainWin : public QMainWindow
                            {
                                public:
                                    MainWin() : QMainWindow()
                                        {
                                        // use a timer to simulate incoming data
                                        QTimer* timer=new QTimer(this);
                                        connect(timer, &QTimer::timeout,this,[this]()
                                        {
                                            static int i=0;
                                            i++;
                            
                                            auto it = childWindows.begin();
                            
                                            while (it != childWindows.end())
                                                {
                                                if (*it==nullptr)   // removed from the vector if child win deleted/closed
                                                    it = childWindows.erase(it);
                                                else
                                                    {
                                                    (**it).setData(QString("Data %1").arg(i).toLatin1());
                                                    ++it;
                                                    }
                                                }
                                        });
                                        
                                        timer->start(1000);
                            
                                        for(int i=0; i<3; i++)
                                            {
                                            ChildWindow* w=new ChildWindow;
                                            w->setObjectName(QString("Child %1").arg(i+1));
                                            w->setWindowTitle(w->objectName());
                                            w->show();
                                            childWindows<<w;
                                            }
                            
                                        }
                            
                                private:
                                    QVector<QPointer<ChildWindow> > childWindows;
                            
                            };
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication app(argc, argv);
                            
                            MainWin win;
                            win.setWindowTitle("Main WIndow");
                            win.show();
                                return app.exec();
                            }
                            
                            T Offline
                            T Offline
                            tilz0R
                            wrote on last edited by
                            #12

                            Thanks to all - I learnt something new, especially who shall call connect to signals.

                            1 Reply Last reply
                            0
                            • T tilz0R has marked this topic as solved on

                            • Login

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