Problem with qwtPlot / not matching function for call to...



  • Hi all,

    I wrote a application that plot data with the qwtPlot library.
    It will not work fine.
    First I try to plot xData and yData in a while loop 5 times with function populate() in plot.cpp.
    When I call the function populate() at the end from the constructor Plot::Plot..., the plot are correctly.
    But when I call the function populate() from the module modbusadapter.cpp, I became an error message:

    no matching function for call to 'Plot::Plot(ModbusAdapter* const)'
    candidates are: Plot::Plot(QWidget*)
    note: Plot::Plot(const Plot&)

    I receive the error only when I allocate memory for plot object in this form:

    @plotNewDensity=new Plot(this);@

    without the attribute 'this', I can compile, but when I call function populate() in modbusadapter.cpp (after modbus response),
    I can see in debug mode that the code jumps in populate(), but without plots...

    Here any code segments:

    plot.h
    @#ifndef PLOT_H
    #define PLOT_H

    #include <qapplication.h>
    #include <qlayout.h>
    #include <qwt_plot.h>
    #include <qwt_plot_grid.h>
    #include <qwt_plot_marker.h>
    #include <qwt_plot_curve.h>
    #include <qwt_legend.h>
    #include <qwt_series_data.h>
    #include <qwt_plot_canvas.h>
    #include <qwt_plot_panner.h>
    #include <qwt_plot_magnifier.h>
    #include <qwt_text.h>
    #include <qwt_math.h>
    #include <math.h>

    #define SIZE 15

    class Plot : public QwtPlot
    {
    Q_OBJECT

    public:
    Plot( QWidget *parent = NULL);
    ~Plot();
    void setPlotValue(double value);
    void populate();

    protected:
    virtual void resizeEvent( QResizeEvent * );

    private:
    //void populate();
    void updateGradient();
    double cntX;
    QwtPlotCurve *density;
    double xData[SIZE];
    double yData[SIZE];

    public slots:
    void addNewValue(double value);
    //void populate();

    signals:

    };
    #endif // PLOT_H@

    plot.cpp
    @#include "plot.h"

    Plot::Plot(QWidget *parent):
    QwtPlot( parent )
    {
    xData[0] = 0;
    yData[0] = 0;

    // Insert new density curve
    density = new QwtPlotCurve("y = density");
    //density->setRenderHint(QwtPlotItem::RenderAntialiased);
    density->setStyle(QwtPlotCurve::Lines);
    density->setLegendAttribute(QwtPlotCurve::LegendShowLine, true);
    density->setPen(QPen(Qt::red));
    density->attach(this);
    
    // Draw grid
    QwtPlotGrid *grid = new QwtPlotGrid();
    grid->setPen(QPen(Qt::gray, 0.0, Qt::DotLine));
    grid->enableX(true);
    grid->enableXMin(true);
    grid->enableY(true);
    grid->enableYMin(false);
    grid->attach(this);
    
    // Insert markers
    //  ...a horizontal line at y = 0...
    QwtPlotMarker *mY = new QwtPlotMarker();
    mY->setLabel(QString::fromLatin1("y = 0"));
    mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop);
    mY->setLineStyle(QwtPlotMarker::HLine);
    mY->setYValue(0.0);
    mY->attach(this);
    
    //  ...a vertical line at x = 0...
    QwtPlotMarker *mX = new QwtPlotMarker();
    mX->setLabel(QString::fromLatin1("x = 0"));
    mX->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom);
    mX->setLabelOrientation(Qt::Vertical);
    mX->setLineStyle(QwtPlotMarker::VLine);
    mX->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
    mX->setXValue(0.0);
    mX->attach(this);
    
    // init private member
    //cntX= 0.0;
    // init function setPlotValue
    //setPlotValue(0.0);
    //plotGPS=new QwtPlotCurve();
    
    // panning with the left mouse button
    (void) new QwtPlotPanner( canvas() );
    
    // zoom in/out with the wheel
    (void) new QwtPlotMagnifier( canvas() );
    
    setAutoFillBackground( true );
    setPalette( QPalette( QColor( 165, 193, 228 ) ) );
    updateGradient();
    
    setTitle("A Simple QwtPlot Demonstration");
    insertLegend(new QwtLegend(), QwtPlot::RightLegend);
    
    // axes
    setAxisTitle(xBottom, "x --&gt;" );
    setAxisScale(xBottom, 0.0, 10.0);
    
    setAxisTitle(yLeft, "y --&gt;");
    setAxisScale(yLeft, -1.0, 1.0);
    
    // canvas
    canvas()->setLineWidth( 1 );
    canvas()->setFrameStyle( QFrame::Box | QFrame::Plain );
    canvas()->setBorderRadius( 15 );
    
    QPalette canvasPalette( Qt::white );
    canvasPalette.setColor( QPalette::Foreground, QColor( 133, 190, 232 ) );
    canvas()->setPalette( canvasPalette );
    
    //populate();    // when I call here, the plots are correctly...
    

    }

    Plot::~Plot()
    {

    }

    void Plot::populate()
    {
    qWarning()<< "Plot : populate()";

    double maxD = 0;
    double minD = 1;
    double maxS = 0;
    double minS = 1;
    
    double dens = 2.0;
    unsigned int sample = 0;
    unsigned int x = 0;
    unsigned int y = 0;
    
    while(sample < 5)
    {
        xData[x++]= sample;
        yData[y++]= dens;
    
        setAxisScale(xBottom, (int)xData[dataCount-1]-iHistorySize, (int)xData[dataCount-1]+1);
        setAxisScale(yLeft, (int)min-1, (int)max+1);
    
        maxS = sample;
        minS = sample++;
        maxD = dens;
        minD = dens++;
    
        setAxisScale(xBottom, (int)minS-1, (int)maxS+1);
        setAxisScale(yLeft,   (int)minD-1, (int)maxD+1);
    
        density->setSamples(xData, yData, sample);
        // Call "replot()" to refresh plot displaying
        replot();
    }
    

    }
    ...
    ...
    ...@



  • and here the rest:

    modbusadapter.h
    @#ifndef MODBUSADAPTER_H
    #define MODBUSADAPTER_H

    #include <QObject>
    #include "modbus.h"
    #include "registersmodel.h"
    #include "rawdatamodel.h"
    #include <QTimer>
    #include "eutils.h"

    #include "plot.h"

    class ModbusAdapter : public QObject
    {
    Q_OBJECT

    public:
    explicit ModbusAdapter(QObject *parent = 0);

     void busMonitorRequestData(uint8_t * data,uint8_t dataLen);
     void busMonitorResponseData(uint8_t * data,uint8_t dataLen);
    
     void modbusConnectRTU(QString port, int baud, QChar parity, int dataBits, int stopBits);
     void modbusConnectTCP(QString ip, int port);
     void modbusDisConnect();
     void modbusRequestData(int slave, int functionCode, int startAddress, int noOfItems);
     RegistersModel *regModel;
     RawDataModel *rawModel;
     Plot *plotNewDensity;
     bool isConnected();
    

    ...
    ...
    ...@

    modbusadapter.cpp
    @#include "modbusadapter.h"
    #include <QMessageBox>
    #include <QtDebug>
    #include <errno.h>

    ModbusAdapter *m_instance;
    static const int DBG = false; //Debug messages from libmodbus

    ModbusAdapter::ModbusAdapter(QObject *parent) :
    QObject(parent),
    m_modbus(NULL)
    {
    m_instance=this;
    regModel=new RegistersModel(this);
    rawModel=new RawDataModel(this);

    plotNewDensity=new Plot(this);
    
    m_connected = false;
    

    }
    ...
    ...
    ...
    // after modbus response
    plotNewDensity->populate();
    ...
    ...
    ...@

    can help anywhere plaese?

    thanks and sorry for my english ;)

    best regards
    Anthony


  • Moderators

    You need to look at the base class of ModbusAdapter which is QObject.

    Plot::Plot(QWidget *parent) is expecting a QWidget pointer. QWidget has also QObject as a base class, but the compiler cannot match. That is the error message.

    You can use QWidget as base class for ModBusAdapter. That should solve the matching problem. However, you need to check for side effects possibly arising.



  • hello koahnig, thanks for the advice...

    Now I use QWidget as base class for ModBusAdapter in this way:

    @class ModbusAdapter : public QWidget
    {
    Q_OBJECT

    public:
    explicit ModbusAdapter(QWidget *parent = 0);
    ...
    ...
    ...@

    and

    @ModbusAdapter::ModbusAdapter(QWidget *parent) :
    QWidget(parent),
    m_modbus(NULL)
    {
    m_instance=this;
    regModel=new RegistersModel(this);
    rawModel=new RawDataModel(this);

    plotNewDensity=new Plot(this);
    
    m_connected = false;
    

    }@

    I can compile, but when I jump in populate() from modbusadaapter.cpp after modbus response, still I don't have nothing plots...
    When I debug I see again that the jump in populate is ok and the steps and values also but without plots...

    What could be the problem?

    !https://www.dropbox.com/s/r09yyx8vgf9em5t/plotOk.gif (plot ok, when i call populate() in constructor Plot::Plot...)!

    !https://www.dropbox.com/s/4mz55fx8qp58if8/plotNok.gif (without plots, when i call populate() in modbusadapter.cpp after modbus response)!


  • Moderators

    @
    void Plot::populate()
    {
    qWarning()<< "Plot : populate()";

    double maxD = 0;
    double minD = 1;
    double maxS = 0;
    double minS = 1;
    
    double dens = 2.0;
    unsigned int sample = 0;
    unsigned int x = 0;
    unsigned int y = 0;
    
    while(sample < 5)
    {
        xData[x++]= sample;
        yData[y++]= dens;
    
        setAxisScale(xBottom, (int)xData[dataCount-1]-iHistorySize, (int)xData[dataCount-1]+1);
        setAxisScale(yLeft, (int)min-1, (int)max+1);
    
        maxS = sample;
        minS = sample++;
        maxD = dens;
        minD = dens++;
    
        setAxisScale(xBottom, (int)minS-1, (int)maxS+1);
        setAxisScale(yLeft,   (int)minD-1, (int)maxD+1);
    
        density->setSamples(xData, yData, sample);
        // Call "replot()" to refresh plot displaying
    }
    setAutoReplot(true);
    replot();
    

    }
    @

    See, if this helps.



  • with

    @setAutoReplot(true);@

    it still doesn't plot nothing...



  • the main looks like

    @#include <QtGui/QApplication>
    #include "mainwindow.h"
    #include "plot.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    Plot *plot = new Plot();
    
    // We put a dummy widget around to have
    // so that Qt paints a widget background
    // when resizing
    
    QWidget window;
    QHBoxLayout *layout = new QHBoxLayout( &window );
    layout->setContentsMargins( 0, 0, 0, 0 );
    layout->addWidget( plot );
    
    window.resize(600,400);
    window.show();
    
    MainWindow w;
    w.show();
    
    return a.exec(&#41;;
    

    }@

    maybe is that anything wrong?



  • do I declare also anything in mainwindow?

    here the code:

    mainwindow.h
    @#ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QSettings>
    #include <QLabel>
    #include <QTimer>
    #include "modbus.h"
    #include "forms/about.h"
    #include "forms/settingsmodbusrtu.h"
    #include "forms/settingsmodbustcp.h"
    #include "forms/settings.h"
    #include "forms/busmonitor.h"
    #include "modbusadapter.h"

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    private:
    Ui::MainWindow *ui;
    //UI - Dialogs
    About *m_dlgAbout;
    SettingsModbusRTU *m_dlgModbusRTU;
    SettingsModbusTCP *m_dlgModbusTCP;
    Settings *m_dlgSettings;
    BusMonitor *m_busMonitor;

    QSettings *m_modbusCommSettings;
    void updateStatusBar();
    QLabel *m_statusText;
    QWidget *m_statusInd;
    ModbusAdapter *m_modbus;
    void modbusConnect(bool connect);
    QTimer *m_pollTimer;
    

    private slots:
    void showSettingsModbusRTU();
    void showSettingsModbusTCP();
    void showSettings();
    void showBusMonitor();
    void changedModbusMode(int currIndex);
    void changedFunctionCode(int currIndex);
    void changedBase(int currIndex);
    void changedReqCycle(bool value);
    void changedConnect(bool value);
    void changedSlaveIP();
    void addItems();
    void clearItems();
    void request();
    void pollRequestForData();

    };

    #endif // MAINWINDOW_H
    @

    now I have nothing in mainwindow regarding plot...


  • Moderators

    Did you use one of the examples?
    If so, maybe you should go back and change step by step. Unfortunately, I do not have enough experience with qwt to help you further.



  • yes I have a example. The difference is that the plot layout are implemented directly in mainwindow looks like: !https://www.dropbox.com/s/a9qih7t7ubzq04d/EP24control.gif ()!

    in my version I have two window one for plot and the other for modbus communication

    here the code of example:

    plot.h
    @#ifndef PLOT_H
    #define PLOT_H

    #include <QVector>
    #include <qwt_plot.h>
    #include <qwt_system_clock.h>
    #include <qwt_plot_curve.h>

    #define BUFFERSIZE 36000 // Data buffer size (voluntarly laaarge! => 36000 at 10data/s = 1h)

    class plot : public QwtPlot
    {
    Q_OBJECT

    public:
    plot(QWidget * = NULL);
    virtual ~plot();
    void start();
    void rescaleXaxis(int scale);

    private:
    QwtPlot *d_plot;

    QwtPlotCurve *d_curve;
    double  xData[BUFFERSIZE];     // x-data table
    double  yData[BUFFERSIZE];     // y-data table
    int     dataCount;              // data counter
    double  timeData[BUFFERSIZE];
    int     iHistorySize;           // history size
    
    QwtSystemClock d_clock;
    

    public slots:
    void slot_addPoint(double value);
    };

    #endif // PLOT_H
    @

    plot.cpp
    @#include "plot.h"
    #include <qwt_plot_grid.h>
    #include <qwt_plot_layout.h>
    #include <qwt_plot_canvas.h>
    #include <qwt_plot_marker.h>
    #include <qwt_plot_curve.h>
    #include <qwt_plot_directpainter.h>
    #include <qwt_curve_fitter.h>
    #include <qwt_painter.h>
    #include <QtDebug>

    plot::plot(QWidget *parent):
    QwtPlot(parent)
    {
    // Initialize variables
    dataCount = 0;
    iHistorySize = 60;
    xData[dataCount] = 0;

    // Set x-axis scale
    rescaleXaxis(iHistorySize);
    
    // Set x-axis label
    setAxisTitle(xBottom, "Time [s]");
    
    // Draw grid
    QwtPlotGrid *grid = new QwtPlotGrid();
    grid->setPen(QPen(Qt::gray, 0.0, Qt::DotLine));
    grid->enableX(true);
    grid->enableXMin(true);
    grid->enableY(true);
    grid->enableYMin(false);
    grid->attach(this);
    
    // Draw curve
    d_curve = new QwtPlotCurve();
    d_curve->setStyle(QwtPlotCurve::Lines);
    d_curve->setPen(QPen(Qt::blue));
    d_curve->attach(this);
    

    }

    plot::~plot()
    {

    }

    void plot::start()
    {
    if(d_clock.isNull())
    {
    // Start clock
    d_clock.start();
    }
    else
    {
    dataCount = 0;
    xData[dataCount] = 0;

        // Reset x-axis
        rescaleXaxis(iHistorySize);
    
        // Restart clock
        d_clock.restart();
    }
    

    }

    // SLOTS
    void plot::slot_addPoint(double value)
    {
    double max = 0;
    double min = 1;

    // Get elapsed time in seconds
    xData[dataCount] = (double)(d_clock.elapsed() / 1000);
    
    // Add y-data
    yData[dataCount] = value;
    
    if(xData[dataCount] < BUFFERSIZE)
    {
        // Increment data counter
        dataCount++;
    }
    else
    {
        // Shift once
        for(int i=1;i<=dataCount;i++)
        {
            xData[i-1] = xData[i];
            yData[i-1] = yData[i];
        }
    }
    
    // Rescale x-axis
    rescaleXaxis(iHistorySize);
    
    // Rescale y-axis
    for(int i=0; i<dataCount; i++)
    {
         if(yData[i] > max)max = yData[i];
         if((yData[i] < 0) && (yData[i] < min))min = yData[i];
    }
    setAxisScale(yLeft, (int)min-1, (int)max+1);
    
    // Set samples on the curve
    d_curve->setSamples(xData, yData, dataCount);
    
    // Call "replot()" to refresh plot displaying
    replot();
    

    }

    void plot::rescaleXaxis(int scale)
    {
    // set scale value to iHistorySize
    iHistorySize = scale;

    // if timer not existing of if current time is less than history size
    if(d_clock.isNull() || (xData[dataCount-1] < iHistorySize))
    {
        // Set x-axis scale
        setAxisScale(xBottom, 0., iHistorySize);
    }
    else
    {
        // Set x-axis scale
        setAxisScale(xBottom, (int)xData[dataCount-1]-iHistorySize, (int)xData[dataCount-1]+1);
    }
    
    // Call "replot()" to refresh plot displaying
    replot();
    

    }
    @

    main
    @#include <QtGui/QApplication>
    #include "mainwindow.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;

    // Window icon
    QPixmap p(":/icones/progicon");
    w.setWindowIcon(p);
    w.setWindowTitle("EP24control v1.0.0");
    
    // Window background color
    QPalette pal = w.palette();
    pal.setColor(w.backgroundRole(), QColor(210,220,230));
    w.setPalette(pal);
    
    w.resize(800,600);
    w.show();
    
    return a.exec(&#41;;
    

    }
    @



  • and here the

    mainwindow.h
    @#ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QComboBox>
    #include <QPushButton>
    #include <QLabel>
    #include <QSpinBox>
    #include <QLayout>
    #include <QGroupBox>
    #include <QFile>
    #include <QTextStream>
    #include <QLineEdit>
    #include <QDateTime>
    #include "comthread.h"
    #include "plot.h"
    #include "led.h"

    class MainWindow : public QWidget
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    private:
    void refreshComPortList(QComboBox *myComboBox);
    ComThread *comThread;
    ...
    ...
    ...
    plot *ui_voltagePlot;
    plot *ui_currentPlot;
    plot *ui_temperaturePlot;
    ...
    ...
    ...
    @

    and mainwindow.cpp
    @#include <QDateTime>
    #include <QFileDialog>
    #include "mainwindow.h"
    #include <QDebug>

    MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent)
    {
    ...
    ...
    ...
    // Voltage plot
    ui_voltagePlot = new plot(this);
    ui_voltagePlot->setAxisScale(QwtPlot::yLeft, 0., 16.);
    ui_voltagePlot->setAxisTitle(QwtPlot::yLeft, "Voltage [V]");
    // Current plot
    ui_currentPlot = new plot(this);
    ui_currentPlot->setAxisScale(QwtPlot::yLeft, 0., 10.);
    ui_currentPlot->setAxisTitle(QwtPlot::yLeft, "Current [A]");
    // Temperature plot
    ui_temperaturePlot = new plot(this);
    ui_temperaturePlot->setAxisScale(QwtPlot::yLeft, -20., 50.);
    ui_temperaturePlot->setAxisTitle(QwtPlot::yLeft, "Temp. [°C]");
    ...
    ...
    ...
    // === END OF USER INTERFACE ELEMENTS ===

    // === LAYOUT ===
    

    ...
    ...
    ...

    QVBoxLayout *plotLayout = new QVBoxLayout();
    plotLayout->addWidget(ui_voltagePlot);
    plotLayout->addWidget(ui_currentPlot);
    plotLayout->addWidget(ui_temperaturePlot);
    
    QGridLayout *layout = new QGridLayout();
    layout->addLayout(plotLayout, 0, 0, 6, 1);
    

    ...
    ...
    ...

        connect(comThread, SIGNAL(vComSignalVbat(double)), ui_voltagePlot, SLOT(slot_addPoint(double)));
        connect(comThread, SIGNAL(vComSignalCbat(double)), ui_currentPlot, SLOT(slot_addPoint(double)));
        connect(comThread, SIGNAL(vComSignalTonb(double)), ui_temperaturePlot, SLOT(slot_addPoint(double)));
    

    ...
    ....
    ....

        // Start plot curves creation
        ui_voltagePlot->start();
        ui_currentPlot->start();
        ui_temperaturePlot->start();
    

    ...
    ....
    ...
    // Set new scale
    ui_voltagePlot->rescaleXaxis(iHorizontalScale);
    ui_currentPlot->rescaleXaxis(iHorizontalScale);
    ui_temperaturePlot->rescaleXaxis(iHorizontalScale);

    ...
    ...
    ...
    // Set new scale
    ui_voltagePlot->rescaleXaxis(iHorizontalScale);
    ui_currentPlot->rescaleXaxis(iHorizontalScale);
    ui_temperaturePlot->rescaleXaxis(iHorizontalScale);

    ...
    ...
    @



  • maybe is that the problem, bacause I use two different window with two separate "instance" in my version main...

    !https://www.dropbox.com/s/5bp1p4sqfa3qm77/window_qwtPlot&modbus.gif ()!


Log in to reply
 

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