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,

    0_1557083082781_appData.png

    and when I click on graph button, I have the ChartView displayed.
    0_1557083103060_appGraph.png
    After that, if I click on data button, I go back to data display until that all is fine.

    0_1557083142736_appData.png

    But when I click again to the graph button, it's crashing.

    0_1557082262617_crash.png

    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!


  • Qt Champions 2018

    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...


  • Qt Champions 2018

    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.


  • Qt Champions 2018

    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?


  • Lifetime Qt Champion

    Hi,

    No you can put several different instances of the same class.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.