strategy for structuring app



  • Hi

    Please bear with me, I'am still a bloody C++/Qt beginner even if I already created some minor apps
    just for fun and home use.

    But I always stumble upon the same difficulty... How shall I structure
    my app if there is more that one window in it and data needs to be send
    between the two windows.
    My current goal is to have three classes: a main-mainwindow and a second mainwindow that has as centralwidget a custom derived QChartView. I want to override
    a mouse move event in the QChartView and send the current mouse position to a QLabel the main-mainwindow.

    Now I have two ideas in my mind to exchange the data.
    First, to send it via Signals&Slots and second, to implement setter/getter
    methods between the main-mainwindow and the QChartview class.

    Now for the latter, how would you do this (if at all)?
    Is it possible that I create a setter method in my mainwindow
    that sets a QLabel's text. Now from the QChartview class if a mouseMoveEvent occurs I call somehow the setter method of my mainwindow
    and pass over the mouseposition? But I cannot access my mainwindows object
    in main.cpp:
    MainWindow w.setLabel(QString mousepos)
    from inside the QChartView class?
    Where is my fallacy?

    I usually start with with "New Project->Application->Qt-Widget Application".
    Then I have my mainwindow.h/cpp that gets created in the main.cpp (as MainWindow w;). Then I do it usually wrong by implementing any additional windows inside the mainwindow class and then I wonder why I cant use a setter method in the mainwindow class from the other window.

    Where should i create the second mainwindow object and where the Qchartview (as centralwidget)? Should I do it in main.cpp besides the MainWindow w; so that it acts as a third point where I can use the setter/getter methods of off all the three classes?

    Or should I completly drop this setter/getter methods idea and use
    signal and slots?


  • Lifetime Qt Champion

    Hi
    Often using signals and slots makes a better design as you get better
    encapsulation than using get/setter since the "other" window do not need to know anything about
    the receivers of the signals.
    So for your Chart you could define a new signal
    void MousePos( QString mousepos ); // (signals have no bodies)

    and for mainwindow , define new slot ( both in .h and body in .cpp)
    void MainWindow::MousePos( QString mousepos ) {
    ui->label->setText(mousepos );
    }

    and in main.cpp hook that up to a slot in mainwindow
    (assuming you new the QChart widget there.)
    connect(ChartWinPointer, SIGNAL(MousePos( QString)) , &w, SLOT(MousePos( QString ) ) );

    and in mouseMove in QChart child

    void xxx::mouseMove(xx) {
    QString mp;
    mp=xxxx; // convert to text
    emit MousePos(mp);// tell mainwin ( or what else ever u hook up)
    }

    This way, none of the objects in question need to know much of each other. The QChart will simply emit info to the world
    and what ever class that hooks up a slot to the signal will get informed.
    Its very much like a setter in mainwindow, but free from types of the setter holder and more generic as
    you can have multiple slots connected and all get the string. You could hook up something else than the first mainwindow by
    simply giving it a slot that matches.

    So there is no real fallacy here, just that Qt offer a nice way to allow unrelated objects to communicate in a
    generic way and it will in most cases just work better in the long run than directly calling a other windows functions.
    But since its not (included in) normal c++, it takes some practice to start thinking in terms of signals and slots.



  • Thank you, so I will stick with Signals&Slots and try your approach.
    I'll report back.



  • It works!
    I did it all from scratch and didn't use the templates.
    But I did not wrote anything else to main.cpp than what
    is needed for my mainwindow.

    main.cpp

    #include <QApplication>
    #include "mainwindow.h"
    
    int main(int argc, char *argv[])
    {
       QApplication app(argc,argv);
       MainWindow w;
    
       w.show();
       return app.exec();
    }
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QWidget>
    #include <QMainWindow>
    #include <QLineSeries>
    #include <QChart>
    #include <QChartView>
    #include <QLabel>
    
    class MainWindow : public QWidget
    {
        Q_OBJECT
    public:
        explicit MainWindow(QWidget *parent = nullptr);
    
    private:
        QMainWindow *chartWindow;
        QLabel *labelMouse;
    signals:
    
    public slots:
        void MousePos(QString mp);
    };
    
    #endif // MAINWINDOW_H
    

    mainwondow.cpp

    #include "mainwindow.h"
    #include "mychartview.h"
    
    MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
    {
        this->setWindowTitle("Mainwindow");
        this->resize(100,100);
        chartWindow = new QMainWindow(this);
        chartWindow->setWindowTitle("Chartwindow");
    
        QChart *chart = new QChart();
        QLineSeries *series = new QLineSeries();
        series->append(1,2);
        series->append(2,4);
        series->append(3,5);
        series->append(4,7);
        chart->addSeries(series);
        chart->createDefaultAxes();
    
        MyChartView *chartView = new MyChartView(chart);
        chartWindow->setCentralWidget(chartView);
        chartWindow->show();
        chartWindow->move(30,30);
    
        labelMouse = new QLabel("n/a",this);
        labelMouse->setStyleSheet("font-size:14pt;");
        labelMouse->resize(100,50);
        connect(chartView,&MyChartView::mousePos,this,&MainWindow::MousePos);
    }
    
    void MainWindow::MousePos(QString mp)
    {
        labelMouse->setText(mp);
    }
    

    mychartview.h

    #ifndef MYCHARTVIEW_H
    #define MYCHARTVIEW_H
    
    #include <QObject>
    #include <QChartView>
    QT_CHARTS_USE_NAMESPACE
    
    class MyChartView : public QChartView
    {
        Q_OBJECT
    public:
        explicit MyChartView(QChart *chart, QWidget *parent = nullptr);
    
    protected:
        void mouseMoveEvent(QMouseEvent *event)override;
    
    signals:
        void mousePos(QString mp);
    };
    
    #endif // MYCHARTVIEW_H
    

    mychartview.cpp

    #include "mychartview.h"
    
    
    MyChartView::MyChartView(QChart *chart, QWidget *parent)
        :QChartView(chart, parent)
    {
    }
    
    void MyChartView::mouseMoveEvent(QMouseEvent *event)
    {
        QString xpos = QString::number(event->pos().x());
        QString ypos = QString::number(event->pos().y());
        QString mpos = xpos + "," + ypos;
        emit mousePos(mpos);
    }
    

    I can now see the x,y position of my mouse in the QChartview.
    0_1515397619605_Bildschirmfoto_2018-01-08_08-45-40.png
    My ultimate goal is to be able to somehow select an x range from the QLineSeries with the mouse and send the selected x-range to my mainwindow. I currently have no idea how to do that but I will do search, maybe someone already has done that.


Log in to reply
 

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