Unsolved Using QSerialPort in multi widget application
-
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
-
@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 aQSerialPort
, 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. -
@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 ?
-
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) -
@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; }
-
@viniltc
Hi
The Instance pointer is where you create the MainWindow.
often in main.cppint 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. -
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 yourQSerialPort
a member of yourMainWindow
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) havestatic
(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 viaMainWindow::serial
. [I assume you just have typos where sometimes your variable is namedserial
and sometimesserial1
.]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. -
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.
-
-
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?
-
@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 theconnect()
line as opposed to from the linker, but: you do not show, but in yourtetraserial.cpp
(not.h
) have you placed the definitionstatic QSerialPort *tetraSerial::serialObject;
somewhere? -
@JonB said in Using QSerialPort in multi widget application:
static QSerialPort *tetraSerial::serialObject;
@JonB
The error is thrown from themainWindow.cpp
Also, I can't place
static QSerialPort *tetraSerial::serialObject;
in the class definition intetraserial.h
either ; it says extra qualification on member 'serialObject'Any thought!?
-
@viniltc
I did state that line was specifically not to be put intetraserial.h
, it belongs intetraserial.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 includetetraSerial.h
there, you wouldn't have failed to do that would you?? -
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 define
QSerialPort *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??
-
cannot connect <null>::readydata() Mainwindow::serialRecived
readydata()
orreadyRead()
? 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!
-
@viniltc said in Using QSerialPort in multi widget application:
cannot connect <null>::readydata() Mainwindow::serialRecived
@JonB
Sorry my bad yes, that'sreadyRead()
Btw thanks a lot @JonB for your suggestions. -
-
There's no need to make your serial port static.
You don't check whether the
open
call was successful. -
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.
-
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.