Is data received from serial port possible to view on two forms?
-
@Shivam-Sharma
As @J-Hilk has said. And further to that: (unless a Qt expert contradicts me) you should never be includingmainwindow.h
into anything other thanmainwindow.cpp
and yourmain.cpp
, not into any other UI stuff you define. Keeps it clean --- they should never need to know about yourMainWindow
class. This is true all over the place: a widget which accesses/opens a "child" widget should include that child's.h
file, but the "child" widgets should never need to know about/include the.h
file of other ("parent") widgets where they might be called from. At least usually. -
This post is deleted!
-
Hi,
One small addition, when passing QString around like that (but it is also valid for other classes), it's a good habit to use const references. This allows to avoid creating unneeded copies.
-
@J-Hilk @JonB Hi guys. Need one more help. If i want to add a push button on the Setup form that connects and disconnects the serial data incoming on both the forms how could I do that.
This is the code for the push button, i can do it on the mainwindow form but unable to do it on the Setup form since it is not being able to access *serial.
Code:
void MainWindow::on_start_toggled(bool checked) { ui->start->setText(ui->start->isChecked() ? "Connect" : "Disconnect"); if (checked) { serial->close(); ui->start->setStyleSheet(QString("QPushButton {background-color: rgb(115, 210, 22);}")); } else { ui->start->setStyleSheet(QString("QPushButton {background-color: red;}")); serial = new QSerialPort(this); serial = new QSerialPort(this); serial->setPortName("ttyUSB0"); serial->setBaudRate(QSerialPort::Baud9600); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); if( serial->open(QIODevice::ReadWrite)) { qDebug()<<"Port Open OK"; connect(serial, &QSerialPort::readyRead, this, &MainWindow::serialReceived); } else { qDebug()<<"Can't Open Port : " << serial->error(); } serialReceived(); } }
-
@Shivam-Sharma Create a signal in Setup, connect that signal to clicked() signal of the button in Setup and then connect the signal you created in Setup (the first one I mentioned) to a slot in MainWindow where you can enable/disable the serial port.
-
I am sorry, but unable to understand. How do i connect the pushbutton to mainwindow from Setup form, since i cannot inherit the parent class, neither can i create an instance of it. Could you give a demo?
-
@Shivam-Sharma said in Is data received from serial port possible to view on two forms?:
How do i connect the pushbutton to mainwindow from Setup form
You don't, please read more carefully.
class Setup { signals: void onOffSerialPort(); }; void Setup::Setup() { connect(ui->button, &QPushButton::clicked, this, &Setup::onOffSerialButton); } // MainWindow connect(setup, &Setup::onOffSerialButton, this, &MainWindow::onOffSerialButton);
As you can see Setup does not know anything about MainWindow.
-
// MainWindow connect(setup, &Setup::onOffSerialButton, this, &MainWindow::onOffSerialButton);
shouldn't all of this be
onOffSerialPort
and the last part be :
&MainWindow::close); void Mainwindow::close() { serial->close(); }
-
@Shivam-Sharma Sorry, I don't understand what you mean. The code I provided is just to show the idea, you need to adapt it to your needs.
-
let me expand on @jsulm example
first of in your mainwindow, create a new function, defined as a slot
and copy the content of your on button clicked in there
public slots: void toggleSerial(bool checked); //mainwindow.cpp void MainWindow:: toggleSerial(bool checked) { ui->start->setText(ui->start->isChecked() ? "Connect" : "Disconnect"); if (checked) { serial->close(); ui->start->setStyleSheet(QString("QPushButton {background-color: rgb(115, 210, 22);}")); } else { ui->start->setStyleSheet(QString("QPushButton {background-color: red;}")); serial = new QSerialPort(this); serial = new QSerialPort(this); serial->setPortName("ttyUSB0"); serial->setBaudRate(QSerialPort::Baud9600); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); if( serial->open(QIODevice::ReadWrite)) { qDebug()<<"Port Open OK"; connect(serial, &QSerialPort::readyRead, this, &MainWindow::serialReceived); } else { qDebug()<<"Can't Open Port : " << serial->error(); } serialReceived(); } } void MainWindow::on_start_toggled(bool checked) { toggleSerial(checked); }
inside Setup add the signal like @jsulm suggested
signals: void onOffSerialPort(bool checked);
connect your button toggle signal (in Setup) to this signal (constructor of Setup
connect(ui->myButton, &QPushButton:: toggled, this, &Setup:: onOffSerialPort);
and finally
connect thatonOffSerialPort
signal to yourtoggleSerial
slotconnect(setup, &Setup:: onOffSerialPort, this, &MainWindow:: toggleSerial);
one thing to keep in mind, your 2 buttons will now not necessarily show the correct checked status.
I'll let you figure that one out.
-
Error: no member named start in ui::mainwindow,
that is because it isn't able to access the pushbutton from setup window. Help please.
Also:
void MainWindow::on_start_toggled(bool checked)
{
toggleSerial(checked);
}
this also has errors saying: on_start_toggled doesn't match any declaration. -
@Shivam-Sharma
where did you put this ?public slots: void toggleSerial(bool checked);
in mainwindow.h or on setup.h ?
-
in mainwindow.h
-
@Shivam-Sharma said in Is data received from serial port possible to view on two forms?:
that is because it isn't able to access the pushbutton from setup window
I repeat it once more: YOU DO NOT HAVE TO ACCESS THIS BUTTON FROM MAIN WINDOW!
Please show your current code. -
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <info.h> #include <setup.h> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); Info *info; Setup *setup; signals: void newSerialData(QString data); public slots: void toggleSerial(bool checked); private slots: void serialReceived(); void on_infobutton_clicked(); void on_setupbutton_clicked(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include "ui_mainwindow.h" #include <info.h> #include <setup.h> #include <QList> #include <QComboBox> #include <QString> #include <QTextEdit> #include <QTime> #include <QDebug> #include <QSerialPort> #include <QtSerialPort/QSerialPortInfo> #include <QFile> #include <qmath.h> #include <QList> QSerialPort *serial; QString line; QString txt1; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(setup, &Setup::onOffSerialPort, this, &MainWindow::toggleSerial); serial = new QSerialPort(this); serial = new QSerialPort(this); serial->setPortName("ttyUSB0"); serial->setBaudRate(QSerialPort::Baud9600); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); if( serial->open(QIODevice::ReadWrite)) { qDebug()<<"Port Open OK"; connect(serial, &QSerialPort::readyRead, this, &MainWindow::serialReceived); } else { qDebug()<<"Can't Open Port : " << serial->error(); } serialReceived(); } MainWindow::~MainWindow() { delete ui; serial->close(); } char *get_field(char *str,int fld) { static char t0[512]; int i=0,j=0,k=0; while(i<512) { if(*(str+i) == ',' || *(str+i) == '\n') { if (fld==j) return t0; j++; t0[0]=0; k=0; } else { t0[k++]=*(str+i); t0[k]=0; } i++; } t0[0]=0; return t0; } int checksum_gps(char *str) { unsigned char cs=0,sum=0,i=0; char sCS[8], exit =0; while (i<250 && !exit) { if(*(str+i) == '*') { sum=0; break; } if(sum) cs^=*(str+i); if(*(str+i) == '$') sum=1; if(*(str+i) == 0) exit=1; i++; } sprintf(sCS,"%02X",cs); if (memcmp(sCS,str+i+1,2)==0) return 1; return 0; } char *timestamp(void) { static char t0[128]; long ms; time_t now; struct tm *t; struct timespec spec; time(&now); t= localtime(&now); clock_gettime(CLOCK_REALTIME, &spec); ms= round(spec.tv_nsec/1.0e6); sprintf(t0, "%04d/%02d/%02d %02d:%02d:%02d.%03ld ", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, ms); return t0; } void MainWindow::serialReceived() { QByteArray serialData; serialData = serial->readAll(); QString static receivedData = QString::fromStdString(serialData.toStdString()); char t0[512]; static char t1[512]; static int wp=0; unsigned int i=0; QString filename="/home/user/Desktop/Programs/MainCBOT2/entrydata.txt"; QFile file( filename ); if(file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { QTextStream stream( &file ); strcpy(t0,serialData); for (i=0;i<strlen(t0);i++) { t1[wp++]=t0[i]; wp%=512; t1[wp]=0; if(t0[i] == '\n') { wp=0; if(checksum_gps(t1)) { if(memcmp("$GPRMC",t1,6)==0) { unsigned int latcnt1=0, log_cnt1=0,spdcnt=0, cogcnt=0; char cog[20]; char spd[20]; char lat1[20], lg1[20]; for(i=20;i<28;i++) { lat1[latcnt1++]=t1[i]; } float j=atof(lat1); float k=(int)(j/100); float minlat = j - ( k * 100 ); float ddeglat = k + ( minlat / 60 ); ui->latitude->setText(QString::number(ddeglat,'f')); for(i=33;i<42;i++) { lg1[log_cnt1++]=t1[i]; } float p=atof(lg1); float q=(int)(p/100); float minlong = p - ( q * 100 ); float ddeglong = q + ( minlong / 60 ); ui->longitude->setText(QString::number(ddeglong,'f')); for (i=45;i<50;i++) { spd[spdcnt++]=t1[i]; } float r=atof(spd); ui->speed->setText(QString::number(r,'f',4)); for (i=50;i<56;i++) { cog[cogcnt++]=t1[i]; } float u=atof((cog)); float w=u*0.514444; ui->cog->setText(QString::number(w,'f',4)); stream<<strcat(t1,timestamp()); ui->rece->setText(t1); emit newSerialData(t1); fflush(stdout); } } } } file.close(); } ui->timest->setText(timestamp()); } void MainWindow::on_infobutton_clicked() { info = new Info(this); info->show(); } void MainWindow::on_setupbutton_clicked() { setup = new Setup(this); setup->show(); connect(this, &MainWindow::newSerialData, setup, &Setup::onNewSerialData); } void MainWindow:: toggleSerial(bool checked) { ui->start->setText(ui->start->isChecked() ? "Connect" : "Disconnect"); if (checked) { serial->close(); ui->start->setStyleSheet(QString("QPushButton {background-color: rgb(115, 210, 22);}")); } else { ui->start->setStyleSheet(QString("QPushButton {background-color: red;}")); serial = new QSerialPort(this); serial = new QSerialPort(this); serial->setPortName("ttyUSB0"); serial->setBaudRate(QSerialPort::Baud9600); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); if( serial->open(QIODevice::ReadWrite)) { qDebug()<<"Port Open OK"; connect(serial, &QSerialPort::readyRead, this, &MainWindow::serialReceived); } else { qDebug()<<"Can't Open Port : " << serial->error(); } serialReceived(); } } void MainWindow::on_start_toggled(bool checked) { toggleSerial(checked); }
#ifndef SETUP_H #define SETUP_H #include <QDialog> namespace Ui { class Setup; } class Setup : public QDialog { Q_OBJECT public: explicit Setup(QWidget *parent = nullptr); ~Setup(); public slots: void onNewSerialData(QString data); signals: void onOffSerialPort(bool checked); private: Ui::Setup *ui; }; #endif // SETUP_H
#include "setup.h" #include "ui_setup.h" #include <QSerialPortInfo> #include <QFile> #include <QSerialPort> Setup::Setup(QWidget *parent) : QDialog(parent), ui(new Ui::Setup) { ui->setupUi(this); ui->start->setCheckable(true); connect(ui->start, &QPushButton::toggled, this, &Setup::onOffSerialPort); QList<QSerialPortInfo> list; list = QSerialPortInfo::availablePorts(); for (int i= 0; i < list.length(); i++) { ui->comboBox->addItem(list[i].portName()); } ui->baudratebox->setInsertPolicy(QComboBox::NoInsert); ui->baudratebox->addItem(QStringLiteral("9600"), QSerialPort::Baud9600); ui->baudratebox->addItem(QStringLiteral("19200"), QSerialPort::Baud19200); ui->baudratebox->addItem(QStringLiteral("38400"), QSerialPort::Baud38400); ui->baudratebox->addItem(QStringLiteral("115200"), QSerialPort::Baud115200); } Setup::~Setup() { delete ui; } void Setup::onNewSerialData(QString data) { ui->receiver->append(data); }
-
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(setup, &Setup::onOffSerialPort, this, &MainWindow::toggleSerial);
the connect here is wrong, I think I said, you should place it where you create (new Setup(this)) the setup object.
that would be here
void MainWindow::on_setupbutton_clicked() { setup = new Setup(this); setup->show(); connect(this, &MainWindow::newSerialData, setup, &Setup::onNewSerialData); }
Error: no member named start in ui::mainwindow,
We don't see the form (.ui) class of MainWindow did you change the object name of start there ?
Edit: you also removed the
on_start_toggled
declaration in MainWindow.hyou know what, the "ConnectByName" feature is crap anyway don't use it.
Remove on_start_toggled complete,
and add the following in the mainWindow constructor :MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(ui->start, &QPushButton::toggled, this, &MainWindow::toggleSerial);
-
@Shivam-Sharma said in Is data received from serial port possible to view on two forms?:
Also:
void MainWindow::on_start_toggled(bool checked)
{
toggleSerial(checked);
}
this also has errors saying: on_start_toggled doesn't match any declaration.You need to do what it says. Where is your declaration of this method in the
.h
file? I think you had it insetup.h
, if you've moved the method toMainWindow
then obviously you need to move the declaration too. -
This post is deleted!
-
I think there was a miss conception, start is not a toggle button, but a QLabel or something.
Anyway here's a working example
https://github.com/DeiVadder/Topic111960
btw, you leak memory (class instances) all over the place.