Unsolved application crash when setCentralWidget(chartView) at the second time...
-
Hello,
I'm coding small app to get data from sensor on console and following button, have graph from text file where are recorded the data.
When I start the app, all working fine, I receive data,
and when I click on graph button, I have the ChartView displayed.
After that, if I click on data button, I go back to data display until that all is fine.But when I click again to the graph button, it's crashing.
the problem is apparently from read access in my function
void MainWindow::on_actionGraph()
but I don't see where...
the only thing make it stopping crash is to remove the graphic with //setCentralWidget(chartView); inside my function on_actionGraph()
but off course, I need this graph...I try to use a copy of the text file to be sure it's not used by my function
void MainWindow::readData(const QByteArray &data)
but same crash.
here the mainwindow.h
/**************************************************************************** ** ** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> ** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtSerialPort module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QSerialPort> #include <QWinTaskbarButton> #include <QSystemTrayIcon> #include <QtCharts/QChartView> #include <QtCharts/QLineSeries> #include <QtCharts/QValueAxis> #include <QtCharts/QCategoryAxis> QT_BEGIN_NAMESPACE class QLabel; namespace Ui { class MainWindow; } QT_END_NAMESPACE QT_CHARTS_USE_NAMESPACE class Console; class SettingsDialog; class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); void openSerialPort(); QSystemTrayIcon *tray; QIcon icon; QChart *chart = new QChart(); QChartView *chartView = new QChartView(chart); private slots: void closeSerialPort(); void about(); void readData(const QByteArray &data); void handleError(QSerialPort::SerialPortError error); void on_actionGraph(); void on_actionData(); void toconsole(); private: void initActionsConnections(); void showStatusMessage(const QString &message); void keyPressEvent (QKeyEvent *event); Ui::MainWindow *m_ui = nullptr; QLabel *m_status = nullptr; Console *m_console = nullptr; SettingsDialog *m_settings = nullptr; QSerialPort *m_serial = nullptr; }; #endif // MAINWINDOW_H
here the mainwindow.cpp
/**************************************************************************** ** ** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com> ** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtSerialPort module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" #include "console.h" #include "settingsdialog.h" #include <QDebug> #include <QLabel> #include <QMessageBox> #include <QSystemTrayIcon> #include <QIcon> #include <QPixmap> #include <QFileInfo> #include <QDateTime> #include <QByteArray> #include <QtCharts/QChartView> #include <QtCharts/QLineSeries> #include <QtCharts/QValueAxis> #include <QtCharts/QCategoryAxis> #include <QtGui/QMouseEvent> #include <QKeyEvent> QT_CHARTS_USE_NAMESPACE //! [0] MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::MainWindow), m_status(new QLabel), m_console(new Console), m_settings(new SettingsDialog), //! [1] m_serial(new QSerialPort(this)) //! [1] { //! [0] m_ui->setupUi(this); m_console->setEnabled(false); setCentralWidget(m_console); m_ui->actionConnect->setEnabled(true); m_ui->actionDisconnect->setEnabled(false); m_ui->actionQuit->setEnabled(true); m_ui->actionConfigure->setEnabled(true); m_ui->actionGraph->setEnabled(true); m_ui->statusBar->addWidget(m_status); initActionsConnections(); connect(m_serial, &QSerialPort::errorOccurred, this, &MainWindow::handleError); connect(m_serial, &QSerialPort::readyRead, this, &MainWindow::on_actionData); } MainWindow::~MainWindow() { delete m_settings; delete m_ui; } //! [4] void MainWindow::openSerialPort() { const SettingsDialog::Settings p = m_settings->settings(); m_serial->setPortName(p.name); m_serial->setBaudRate(p.baudRate); m_serial->setDataBits(QSerialPort::Data8); m_serial->setParity(QSerialPort::NoParity); m_serial->setStopBits(QSerialPort::OneStop); m_serial->setFlowControl(QSerialPort::NoFlowControl); if (m_serial->open(QIODevice::ReadOnly)) { m_console->setEnabled(true); m_console->setLocalEchoEnabled(p.localEchoEnabled); m_ui->actionConnect->setEnabled(false); m_ui->actionDisconnect->setEnabled(true); m_ui->actionConfigure->setEnabled(false); m_ui->actionGraph->setEnabled(true); m_ui->actionData->setEnabled(false); showStatusMessage(tr("Connected to %1 : %2, %3") .arg(p.name).arg(p.stringBaudRate).arg(p.stringDataBits)); } else { QMessageBox::critical(this, tr("Error"), m_serial->errorString()); showStatusMessage(tr("Open error")); } tray = new QSystemTrayIcon(this); icon.addFile(":/images/disconnect.png"); tray->setIcon(icon); tray->setVisible(true); tray->show(); } void MainWindow::closeSerialPort() { if (m_serial->isOpen()) m_serial->close(); m_console->setEnabled(false); m_ui->actionConnect->setEnabled(true); m_ui->actionDisconnect->setEnabled(false); m_ui->actionConfigure->setEnabled(true); showStatusMessage(tr("Disconnected")); } void MainWindow::about() { QMessageBox::about(this, tr("About Thermometer"), tr("")); } void MainWindow::readData(const QByteArray &data) { QFile fileOut("d:/Magasin_Temp_Hygro.txt"); fileOut.open(QFile::ReadWrite); QTextStream streamOut(&fileOut); const QChar delimeter = ';' ; QStringList list = streamOut.readAll().split(delimeter); int i=0; int count=list.size(); if (!streamOut.atEnd()) { for( i=0;i<count;i++) { streamOut << list[i]; } }else{ if(data.size()>10) { QDateTime timestamp; timestamp=QDateTime::currentDateTime(); QString time=timestamp.toString("dd/MM/yy hh'h'mm"); streamOut <<time; } for(int x=0;x<data.size();x++) { streamOut << data[x]; } } fileOut.close(); } void MainWindow::handleError(QSerialPort::SerialPortError error) { if (error == QSerialPort::ResourceError) { QMessageBox::critical(this, tr("Critical Error"), m_serial->errorString()); closeSerialPort(); } } //! [8] void MainWindow::initActionsConnections() { connect(m_ui->actionConnect, &QAction::triggered, this, &MainWindow::openSerialPort); connect(m_ui->actionDisconnect, &QAction::triggered, this, &MainWindow::closeSerialPort); connect(m_ui->actionQuit, &QAction::triggered, this, &MainWindow::close); connect(m_ui->actionGraph, &QAction::triggered, this, &MainWindow::closeSerialPort); connect(m_ui->actionGraph, &QAction::triggered, this, &MainWindow::on_actionGraph); connect(m_ui->actionData, &QAction::triggered, this, &MainWindow::toconsole); connect(m_ui->actionData, &QAction::triggered, this, &MainWindow::openSerialPort); connect(m_ui->actionConfigure, &QAction::triggered, m_settings, &SettingsDialog::show); connect(m_ui->actionClear, &QAction::triggered, m_console, &Console::clear); connect(m_ui->actionAbout, &QAction::triggered, this, &MainWindow::about); connect(m_ui->actionAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt); //connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(quitMyApp())); } void MainWindow::keyPressEvent (QKeyEvent *event) { //QKeyEvent *keyEvent = static_cast<QKeyEvent *>(keyEvent); if(event->key()==Qt::Key_Plus) {chartView->chart()->zoomIn();} if(event->key()==Qt::Key_Minus) {chartView->chart()->zoomOut();} if(event->key()==Qt::Key_Left) {chartView->chart()->scroll(-10, 0);} if(event->key()==Qt::Key_Right) {chartView->chart()->scroll(10, 0);} if(event->key()==Qt::Key_Up) {chartView->chart()->scroll(0, 10);} if(event->key()==Qt::Key_Down) {chartView->chart()->scroll(0, -10);} } void MainWindow::showStatusMessage(const QString &message) { m_status->setText(message); } void MainWindow::on_actionGraph() { m_ui->actionGraph->setEnabled(false);//disable graph button m_ui->actionData->setEnabled(true);//able data button QFile fileGraph("d:/Magasin_Temp_Hygro.txt");//select text file with recorded data fileGraph.open(QFile::ReadOnly);//open text file with recorded data int line_count=0; qreal temp=0; QString date; qreal hygro; QLineSeries *temperature = new QLineSeries(); QLineSeries *hygrometrie = new QLineSeries(); QCategoryAxis *axisX = new QCategoryAxis; QCategoryAxis *axisY1 = new QCategoryAxis; QCategoryAxis *axisY = new QCategoryAxis; while( !fileGraph.atEnd())//loop until end of file { QString line=fileGraph.readLine(); QString date=line.split(":")[0]; bool ok = false; temp=line.split(":")[2].toDouble(&ok); hygro=line.split(":")[4].replace(";","").toDouble(&ok); axisX->append(date,line_count); axisY1->append(QString::number(temp),temp); axisY->append(QString::number(hygro),hygro); *temperature <<QPointF(line_count, temp); *hygrometrie <<QPointF(line_count, hygro); line_count++; } chart->addSeries(temperature); chart->addSeries(hygrometrie); temperature->attachAxis(axisX); temperature->attachAxis(axisY1); hygrometrie->attachAxis(axisY); axisX->setLabelsAngle(-90); axisX->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue); axisY1->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue); axisY1->setMin(10); axisY1->setMax(100); axisY1->setLabelsColor(temperature->pen().color()); axisY->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue); axisY->setMin(10); axisY->setMax(100); axisY->setLabelsColor(hygrometrie->pen().color()); chart->addAxis(axisY, Qt::AlignRight); chart->addAxis(axisY1, Qt::AlignLeft); chart->addAxis(axisX, Qt::AlignBottom); chart->setTitle("Revelé Température et humidité Magasin"); chartView->setRenderHint(QPainter::Antialiasing); chartView->chart()->setAxisX(axisX, hygrometrie); chartView->chart()->setAxisY(axisY, hygrometrie); chartView->chart()->setAxisX(axisY1, temperature); setCentralWidget(chartView); fileGraph.close(); } void MainWindow::toconsole() { m_ui->actionGraph->setEnabled(true); m_ui->actionData->setEnabled(false); m_console = new Console; m_console->setEnabled(true); setCentralWidget(m_console); on_actionData(); } void MainWindow::on_actionData() { const QByteArray data= m_serial->readAll(); readData(data); m_console->putData(data); }
thank you very much for your help!
-
I would guess setCentralWidget() is the problem: "Note: QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time."
Don't set a new central widget every time, use e.g. a QStackedWidget -
@Christian-Ehrlicher Thank a lot, I'm trying to understand how stackedWidget is working but is mean not easy only to display graphic or data at need time...
-
What problem do you have? Isn't the description of QStackedWidget not enough?
-
@Christian-Ehrlicher Hello, I have to confess i'm new with c++ and I don't understand how to use stackedWidget. I add stackedWidget with designer, until that it's ok, but after that I don't know, I have to take more time to read documentation.
-
The detailed description I gave you the link to describes exactly what to do.
QStackedWidget *stackedWidget = new QStackedWidget; // or use it from ui -> ui.stackedWidget stackedWidget->addWidget(firstPageWidget); stackedWidget->addWidget(secondPageWidget); stackedWidget->addWidget(thirdPageWidget);
-
@Christian-Ehrlicher I read that yes, but I don't know what is firstPageWidget in stackedWidget->addWidget(firstPageWidget);
I have to make multiple QWidget .h/.cpp?
-
Hi,
No you can put several different instances of the same class.