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. Using QSerialPort in multi widget application
Qt 6.11 is out! See what's new in the release blog

Using QSerialPort in multi widget application

Scheduled Pinned Locked Moved Unsolved General and Desktop
27 Posts 6 Posters 22.7k 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.
  • V viniltc

    Hello all,

    I'm developing a multi-widget Qt desktop application that serially interacts with an embedded device. I'm new to Qt and serial port application development. Let me try to explain my situation in a bit of detail:

    I have a serial port that needs to be configured once as follows (at present it is defined only in one form)

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QtSerialPort/QSerialPort>
    #include <QtSerialPort/QSerialPortInfo>
    #include <QDebug>
    
    QSerialPort *serial;
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        serial = new QSerialPort(this);
        serial->setPortName("com5");
        serial->setBaudRate(1000000); // baudrate 1000000 ..1M
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::HardwareControl); /
        serial->open(QIODevice::ReadWrite);
    
        connect(serial, SIGNAL(readyRead()), this, SLOT(serialRecived()));
     
    }
    

    I need to reuse the opened serial port "serial" in other forms as well for reading or writing.

    Where and how I can configure the serial port in order to access it in multiple forms without repeating configuration?

    for example, if I have to connection in a second widget, how can I access the serial object??

      connect(serial, SIGNAL(readyRead()), this, SLOT(serialRecived()));
    

    Thank you

    Vinil

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

    @viniltc
    Well, in some shape or form you need to create the instance in one module (.cpp file) and then export the declaration through a .h file which other modules who need to access it import. Within reason, there's nothing special about a QSerialPort, in your usage it's like any other "shared-or-global-variable" which you want to access from various files.

    I'm not a C++-er, but perhaps a singleton class would be suitable for your purposes. I remain to be shouted down by C++ experts, but I don't think that the module containing your MainWindow is a great choice for where to define it --- you'd have to include that into other modules, and I prefer not to export the "main" .cpp's header file to other modules if I don't have to.

    1 Reply Last reply
    2
    • V Offline
      V Offline
      viniltc
      wrote on last edited by
      #3

      @JonB
      Thanks a lot for the explanation. I got your points :)

      Even if I try to access the serial object which is defined in MainWindow in another form ,say SecondWindow as follows:

      connect(MainWindow::serial, SIGNAL(readyRead()), this, SLOT(serialRecived()));
      

      I'm getting an error says "invalid use of non-static data member 'serial'.

      Any thoughts? What I'm doing wrong here ?

      mrjjM 1 Reply Last reply
      0
      • V viniltc

        @JonB
        Thanks a lot for the explanation. I got your points :)

        Even if I try to access the serial object which is defined in MainWindow in another form ,say SecondWindow as follows:

        connect(MainWindow::serial, SIGNAL(readyRead()), this, SLOT(serialRecived()));
        

        I'm getting an error says "invalid use of non-static data member 'serial'.

        Any thoughts? What I'm doing wrong here ?

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

        Hi
        the serial in main window is not a static member so you would need to say
        MainWindowInstancePointer->serial to access it. ( and it has to be public)
        ( normally the mainwindow is created in main.cpp and you need that in other class)

        1 Reply Last reply
        1
        • V Offline
          V Offline
          viniltc
          wrote on last edited by
          #5

          @mrjj
          thanks for your response. Sorry I didn't get your point. What is MainWindowInstancePointer in my case? This is my mainwindow.h

          #include <QMainWindow>
          #include <QtSerialPort/QSerialPort>
          #include <QtSerialPort/QSerialPortInfo>
          
          namespace Ui {
          class MainWindow;
          }
          
          class MainWindow : public QMainWindow
          {
              Q_OBJECT
          
          public:
              explicit MainWindow(QWidget *parent = nullptr);
              ~MainWindow();
              QSerialPort *serial1;
              
          
          private:
              Ui::MainWindow *ui;
          };
          
          #endif // MAINWINDOW_H
          
          

          And this is mainwindow.cpp

          #include "mainwindow.h"
          #include "ui_mainwindow.h"
          #include <QtSerialPort/QSerialPort>
          #include <QtSerialPort/QSerialPortInfo>
          #include <QDebug>
          
          
          
          
          MainWindow::MainWindow(QWidget *parent) :
              QMainWindow(parent),
              ui1(new Ui::MainWindow)
          {
              ui->setupUi(this);
              serial1 = new QSerialPort();
              serial1->setPortName("com5");
              serial1->setBaudRate(1000000); // baudrate 1000000 ..1M
              serial1->setDataBits(QSerialPort::Data8);
              serial1->setParity(QSerialPort::NoParity);
              serial1->setStopBits(QSerialPort::OneStop);
              serial1->setFlowControl(QSerialPort::HardwareControl); //Hardware flow control (RTS/CTS), NoFlowControl, SoftwareControl
              serial1->open(QIODevice::ReadWrite);
          
            //  connect(serial1, SIGNAL(readyRead()), this, SLOT(serialRecived()));
          }
          
          MainWindow::~MainWindow()
          {
              delete ui1;
          }
          
          
          mrjjM JonBJ 2 Replies Last reply
          0
          • V viniltc

            @mrjj
            thanks for your response. Sorry I didn't get your point. What is MainWindowInstancePointer in my case? This is my mainwindow.h

            #include <QMainWindow>
            #include <QtSerialPort/QSerialPort>
            #include <QtSerialPort/QSerialPortInfo>
            
            namespace Ui {
            class MainWindow;
            }
            
            class MainWindow : public QMainWindow
            {
                Q_OBJECT
            
            public:
                explicit MainWindow(QWidget *parent = nullptr);
                ~MainWindow();
                QSerialPort *serial1;
                
            
            private:
                Ui::MainWindow *ui;
            };
            
            #endif // MAINWINDOW_H
            
            

            And this is mainwindow.cpp

            #include "mainwindow.h"
            #include "ui_mainwindow.h"
            #include <QtSerialPort/QSerialPort>
            #include <QtSerialPort/QSerialPortInfo>
            #include <QDebug>
            
            
            
            
            MainWindow::MainWindow(QWidget *parent) :
                QMainWindow(parent),
                ui1(new Ui::MainWindow)
            {
                ui->setupUi(this);
                serial1 = new QSerialPort();
                serial1->setPortName("com5");
                serial1->setBaudRate(1000000); // baudrate 1000000 ..1M
                serial1->setDataBits(QSerialPort::Data8);
                serial1->setParity(QSerialPort::NoParity);
                serial1->setStopBits(QSerialPort::OneStop);
                serial1->setFlowControl(QSerialPort::HardwareControl); //Hardware flow control (RTS/CTS), NoFlowControl, SoftwareControl
                serial1->open(QIODevice::ReadWrite);
            
              //  connect(serial1, SIGNAL(readyRead()), this, SLOT(serialRecived()));
            }
            
            MainWindow::~MainWindow()
            {
                delete ui1;
            }
            
            
            mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by mrjj
            #6

            @viniltc
            Hi
            The Instance pointer is where you create the MainWindow.
            often in main.cpp

            int main(int argc, char *argv[])
            {
                QApplication a(argc, argv);
                MainWindow w; <<< that is the instance
                w.show();
            
                return a.exec();
            }
            
            

            However, do you really need to share the actual serial class?
            You could also define some new signals in MainWindow and
            connect other classes to these signals to allow to send via serial.
            Or you could move serial to its own class and both mainwindow and OtherClass could use it via signals.

            1 Reply Last reply
            4
            • V viniltc

              @mrjj
              thanks for your response. Sorry I didn't get your point. What is MainWindowInstancePointer in my case? This is my mainwindow.h

              #include <QMainWindow>
              #include <QtSerialPort/QSerialPort>
              #include <QtSerialPort/QSerialPortInfo>
              
              namespace Ui {
              class MainWindow;
              }
              
              class MainWindow : public QMainWindow
              {
                  Q_OBJECT
              
              public:
                  explicit MainWindow(QWidget *parent = nullptr);
                  ~MainWindow();
                  QSerialPort *serial1;
                  
              
              private:
                  Ui::MainWindow *ui;
              };
              
              #endif // MAINWINDOW_H
              
              

              And this is mainwindow.cpp

              #include "mainwindow.h"
              #include "ui_mainwindow.h"
              #include <QtSerialPort/QSerialPort>
              #include <QtSerialPort/QSerialPortInfo>
              #include <QDebug>
              
              
              
              
              MainWindow::MainWindow(QWidget *parent) :
                  QMainWindow(parent),
                  ui1(new Ui::MainWindow)
              {
                  ui->setupUi(this);
                  serial1 = new QSerialPort();
                  serial1->setPortName("com5");
                  serial1->setBaudRate(1000000); // baudrate 1000000 ..1M
                  serial1->setDataBits(QSerialPort::Data8);
                  serial1->setParity(QSerialPort::NoParity);
                  serial1->setStopBits(QSerialPort::OneStop);
                  serial1->setFlowControl(QSerialPort::HardwareControl); //Hardware flow control (RTS/CTS), NoFlowControl, SoftwareControl
                  serial1->open(QIODevice::ReadWrite);
              
                //  connect(serial1, SIGNAL(readyRead()), this, SLOT(serialRecived()));
              }
              
              MainWindow::~MainWindow()
              {
                  delete ui1;
              }
              
              
              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #7

              @viniltc
              I'm with @mrjj :

              Or you could move serial to its own class and both mainwindow and OtherClass could use it via signals.

              in that I'd put it into its own class file. Though I don't think you then need to communicate with it via signals, that may be a bit more work then you're used to. To me, your serial port object just does not particularly belong as a member of your MainWindow (either instance or class) at all.

              What is MainWindowInstancePointer in my case? This is my mainwindow.h

              It's your public QSerialPort *serial1;. Following what I've said above, because you're making your QSerialPort a member of your MainWindow instance that would mean your other module needs to find & access the current main window instance in order to access that object.

              To make what you've currently work dirtily without doing that, make your declaration (.h file) and definition (.cpp file) have static (I don't do C++ daily so I don't offer the exact code). That will allow you to access it from the other module via MainWindow::serial. [I assume you just have typos where sometimes your variable is named serial and sometimes serial1.]

              I still don't recommend this actual way of doing it, static is not great these days. My thought as I said would be singleton class/object.

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

                Hi,

                As my fellows already wrote: don't implement it that way. You should first explain what exactly your other widgets are going to do with the serial port.

                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
                • V Offline
                  V Offline
                  viniltc
                  wrote on last edited by
                  #9

                  @JonB , @mrjj , @SGaist
                  Thanks a lot, guys. I got your points.

                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    viniltc
                    wrote on last edited by viniltc
                    #10

                    Hi,
                    As per the previous suggestion I was trying to create a singleton class for my serial port module. I have one serial port that needs to be able to read and write in multiple forms.

                    My serial module class as follows :

                    #include "tetraserial.h"
                    
                    tetraSerial::tetraSerial(QObject *parent) : QObject(parent)
                    {
                    
                       serialObject = new QSerialPort();
                       serialObject->setPortName("com5");
                       serialObject->setBaudRate(1000000);
                       serialObject->setDataBits(QSerialPort::Data8);
                       serialObject->setParity(QSerialPort::NoParity);
                       serialObject->setStopBits(QSerialPort::OneStop);
                       serialObject->setFlowControl(QSerialPort::HardwareControl); /
                       serialObject->open(QIODevice::ReadWrite);
                        
                    }
                    

                    and my serial.h as follows

                    #ifndef TETRASERIAL_H
                    #define TETRASERIAL_H
                    
                    #include <QObject>
                    #include <QtSerialPort/QSerialPort>
                    #include <QtSerialPort/QSerialPortInfo>
                    #include <QDebug>
                    
                    class tetraSerial : public QObject
                    {
                        Q_OBJECT
                    public:
                        explicit tetraSerial(QObject *parent = nullptr);
                      static QSerialPort *serialObject;
                    
                    signals:
                    
                    public slots:
                    };
                    
                    #endif // TETRASERIAL_H
                    

                    I was trying to access serialObject from MainWindow as follows:

                     connect(tetraSerial::serialObject, SIGNAL(readyRead()), this, SLOT(serialRecived()))
                    

                    I'm getting an error saying undefined refernce to 'tetraSerial::serialObject'

                    what I'm doing wrong here?

                    JonBJ 1 Reply Last reply
                    0
                    • V viniltc

                      Hi,
                      As per the previous suggestion I was trying to create a singleton class for my serial port module. I have one serial port that needs to be able to read and write in multiple forms.

                      My serial module class as follows :

                      #include "tetraserial.h"
                      
                      tetraSerial::tetraSerial(QObject *parent) : QObject(parent)
                      {
                      
                         serialObject = new QSerialPort();
                         serialObject->setPortName("com5");
                         serialObject->setBaudRate(1000000);
                         serialObject->setDataBits(QSerialPort::Data8);
                         serialObject->setParity(QSerialPort::NoParity);
                         serialObject->setStopBits(QSerialPort::OneStop);
                         serialObject->setFlowControl(QSerialPort::HardwareControl); /
                         serialObject->open(QIODevice::ReadWrite);
                          
                      }
                      

                      and my serial.h as follows

                      #ifndef TETRASERIAL_H
                      #define TETRASERIAL_H
                      
                      #include <QObject>
                      #include <QtSerialPort/QSerialPort>
                      #include <QtSerialPort/QSerialPortInfo>
                      #include <QDebug>
                      
                      class tetraSerial : public QObject
                      {
                          Q_OBJECT
                      public:
                          explicit tetraSerial(QObject *parent = nullptr);
                        static QSerialPort *serialObject;
                      
                      signals:
                      
                      public slots:
                      };
                      
                      #endif // TETRASERIAL_H
                      

                      I was trying to access serialObject from MainWindow as follows:

                       connect(tetraSerial::serialObject, SIGNAL(readyRead()), this, SLOT(serialRecived()))
                      

                      I'm getting an error saying undefined refernce to 'tetraSerial::serialObject'

                      what I'm doing wrong here?

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

                      @viniltc
                      With the usual proviso that my C++ is shaky, and I'm not sure whether it could cause the error if it's against the connect() line as opposed to from the linker, but: you do not show, but in your tetraserial.cpp (not .h) have you placed the definition static QSerialPort *tetraSerial::serialObject; somewhere?

                      1 Reply Last reply
                      1
                      • V Offline
                        V Offline
                        viniltc
                        wrote on last edited by
                        #12

                        @JonB said in Using QSerialPort in multi widget application:

                        static QSerialPort *tetraSerial::serialObject;

                        @JonB
                        The error is thrown from the mainWindow.cpp

                        Also, I can't place static QSerialPort *tetraSerial::serialObject; in the class definition in tetraserial.h either ; it says extra qualification on member 'serialObject'

                        Any thought!?

                        JonBJ 1 Reply Last reply
                        0
                        • V viniltc

                          @JonB said in Using QSerialPort in multi widget application:

                          static QSerialPort *tetraSerial::serialObject;

                          @JonB
                          The error is thrown from the mainWindow.cpp

                          Also, I can't place static QSerialPort *tetraSerial::serialObject; in the class definition in tetraserial.h either ; it says extra qualification on member 'serialObject'

                          Any thought!?

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

                          @viniltc
                          I did state that line was specifically not to be put in tetraserial.h, it belongs in tetraserial.cpp if you do not already have it there.

                          I don't know now about your error in mainWindow.cpp --- unless you have failed to include tetraSerial.h there, you wouldn't have failed to do that would you??

                          1 Reply Last reply
                          1
                          • V Offline
                            V Offline
                            viniltc
                            wrote on last edited by viniltc
                            #14

                            @JonB

                            I modified the .cpp file as follows:

                            #include "tetraserial.h"
                            
                             QSerialPort *tetraSerial::serialObject;
                            
                            
                            tetraSerial::tetraSerial(QObject *parent) : QObject(parent)
                            {
                            
                               serialObject = new QSerialPort(this);
                               serialObject->setPortName("com5");
                               serialObject->setBaudRate(1000000);
                               serialObject->setDataBits(QSerialPort::Data8);
                               serialObject->setParity(QSerialPort::NoParity);
                               serialObject->setStopBits(QSerialPort::OneStop);
                               serialObject->setFlowControl(QSerialPort::HardwareControl);
                               serialObject->open(QIODevice::ReadWrite);
                            
                            }
                            

                            I can't defineQSerialPort *tetraSerial::serialObject as static because it is allowed only inside the class definition.

                            Now It is building but I'm getting a runtime error, it says in the console:

                            cannot connect <null>::readyReady() Mainwindow::serialRecived

                            my connect statement in the main as follows:

                            connect(tetraSerial::serialObject, SIGNAL(readyRead()), this, SLOT(serialRecived()));

                            Any suggestion??

                            JonBJ 1 Reply Last reply
                            0
                            • V viniltc

                              @JonB

                              I modified the .cpp file as follows:

                              #include "tetraserial.h"
                              
                               QSerialPort *tetraSerial::serialObject;
                              
                              
                              tetraSerial::tetraSerial(QObject *parent) : QObject(parent)
                              {
                              
                                 serialObject = new QSerialPort(this);
                                 serialObject->setPortName("com5");
                                 serialObject->setBaudRate(1000000);
                                 serialObject->setDataBits(QSerialPort::Data8);
                                 serialObject->setParity(QSerialPort::NoParity);
                                 serialObject->setStopBits(QSerialPort::OneStop);
                                 serialObject->setFlowControl(QSerialPort::HardwareControl);
                                 serialObject->open(QIODevice::ReadWrite);
                              
                              }
                              

                              I can't defineQSerialPort *tetraSerial::serialObject as static because it is allowed only inside the class definition.

                              Now It is building but I'm getting a runtime error, it says in the console:

                              cannot connect <null>::readyReady() Mainwindow::serialRecived

                              my connect statement in the main as follows:

                              connect(tetraSerial::serialObject, SIGNAL(readyRead()), this, SLOT(serialRecived()));

                              Any suggestion??

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

                              @viniltc

                              cannot connect <null>::readydata() Mainwindow::serialRecived

                              readydata() or readyRead()? Did you copy & paste the error message?

                              TBH this is getting to be serious C++ stuff, so I ought bow out. You need someone who knows his C++ better than I!

                              1 Reply Last reply
                              1
                              • V Offline
                                V Offline
                                viniltc
                                wrote on last edited by
                                #16

                                @viniltc said in Using QSerialPort in multi widget application:

                                cannot connect <null>::readydata() Mainwindow::serialRecived
                                @JonB
                                Sorry my bad yes, that's readyRead()
                                Btw thanks a lot @JonB for your suggestions.

                                1 Reply Last reply
                                0
                                • V Offline
                                  V Offline
                                  viniltc
                                  wrote on last edited by viniltc
                                  #17

                                  @SGaist @mrjj

                                  Any help would be welcome..

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

                                    There's no need to make your serial port static.

                                    You don't check whether the open call was successful.

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

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

                                      hI
                                      Also, im a little concerned by sharing the serial idea.
                                      Its fine for writing to it, however, if you connect say 3 other classed to
                                      readyRead() signal, they all get the signal but whom of them will then read the data ?
                                      and how will you know if that class was the intended receiver of the data?

                                      It would help if you explained more what the app does and its intended design.

                                      V 1 Reply Last reply
                                      3
                                      • SGaistS SGaist

                                        There's no need to make your serial port static.

                                        You don't check whether the open call was successful.

                                        V Offline
                                        V Offline
                                        viniltc
                                        wrote on last edited by
                                        #20

                                        @SGaist

                                        If it's non-static, I'm getting an error saying invalid use of non-static data member 'serialObject

                                        The program is getting crashed from the mainWindow itself

                                        connect(tetraSerial::serialObject, SIGNAL(readyRead()), this, SLOT(serialRecived()));
                                        

                                        Can't find what's wrong with my class definition.

                                        jsulmJ 1 Reply Last reply
                                        0
                                        • V viniltc

                                          @SGaist

                                          If it's non-static, I'm getting an error saying invalid use of non-static data member 'serialObject

                                          The program is getting crashed from the mainWindow itself

                                          connect(tetraSerial::serialObject, SIGNAL(readyRead()), this, SLOT(serialRecived()));
                                          

                                          Can't find what's wrong with my class definition.

                                          jsulmJ Offline
                                          jsulmJ Offline
                                          jsulm
                                          Lifetime Qt Champion
                                          wrote on last edited by
                                          #21

                                          @viniltc You need to use an instance of tetraSerial class

                                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                                          V 1 Reply Last reply
                                          2

                                          • Login

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