Use Qt classes for calculation or basic c++ classes
-
I am designing a program that does some calculations and show to the user the results. The parameters are inputed in Qt custom classes that I have designed. For example:
I have a custom GraphicsItem and as public element I have a custom Widget that holds the parameters imputed by the user.
To make my calculation I need only of the parameters passed by the user. So at the present moment I am just taking some parameters direct from the custom private Widget and passing for the GraphicsItem and later a pass the GraphicsItem as pointer to make my calculations.
My doubt is if a should separate my Qt classes from my basic c++(just for calculation). Example:
@
//This class represents a real river and need calculate the outflow from some inputs
class GraphicsCanal :public QObject, public QGraphicsItem:
{
...
public:
CanalWidget* propriedades;//This widget holds the parameters that I need for the calculation and it's shown
//when the user click in some action button
...
}
@
@
void MainWindow::calcularModelo()
{
GraphicsBacia* bacia;
GraphicsScene* scene = static_cast<GraphicsScene*>(ui->graphicsView->scene());
scene->calcularIndexsRede();
QList<QGraphicsItem*> items = scene->sortItems();
foreach(QGraphicsItem* item,items){
if(item->type() == GraphicsBacia::Type){
bacia = qgraphicsitem_cast<GraphicsBacia*>(item);
//Do some calculation with bacia paramaters
}
}
}
@It's better create a simple c++ class that take GraphicsBacia parameters and then make calculation?
I really don't have a lot experience an I would like to make something simple to understand. Normally you use the Qt custom classes or create simple c++ classes to make the calculations? -
There are a couple different design aspects that you touched.
There are different design models like MV, MVC, MVVM and many more, some of which Qt "uses for it's own types":http://qt-project.org/doc/qt-5/model-view-programming.html.
Whichever model you choose the current trend is that you separate data from the input and presentation. What that means is that you don't hold your data (whatever it might be) in graphical components (eg. a widget, a graphics item etc.). Design as if there was no UI input or display. Make data structure independent of input and output methods, and then add these two "on top" of the data, not as part of it. This effectively decouples the structural components of an app and makes it simpler and compartmentalized. This comes in handy when you want to swap one of the components eg. change input from mouse to touch, or change output from QGraphicsView to OpenGL, move from C++ to QML, from widgets to HTML etc. Generally makes any kind of porting a lot easier because you just switch that component without touching data structure or other components.
What it means in practice is that you would have a class eg. DataClass that would hold your data and know nothing about input, display and UI in general. Then you would make a class eg. InputClass that could modify that data (write-only semantic) and a DisplayClass that could present it (read-only semantic).
In your case this translates to a data structure, the widget that can modify that structure and a graphics item that can display it. You don't want to hold your data in a widget, because this would mean a display item would have to know what a widget is (#include) when accessing the data. Similarly you don't want to keep the data in the graphics item, because that way a widget would have to know (#include) what a graphics item is. Both of these make the separate parts of your app co-dependent, and you generally don't want that.That's one aspect of this. Another is the question if your data structure should inherit a QObject (or some other Qt type). The answer is: it depends. It depends on how you plan to connect the different parts of your app.
Here are a couple of examples to consider and start from:
Approach 1:
@
struct Data { /* ... */ }; //plain old data (POD) typeclass Input : public QWidget {
/* ... /
public:
//depending on what you need:
Input(Data data); //if you want to keep it around for updates
void modifyData(Data* data) const; //modify existing structure
Data* generateData() const; //or create a new one
};class Output : public QGraphicsItem {
/* ... /
public:
//depending on what you need:
Output(const Data data); //to keep it around
void displayData(const Data* data); //or draw on demand
}
@
Approach 2:
@
class Data : QObject {
Q_OBJECT
public:
void setSomeData();
signals:
void someDataChanged();
};class Input : public QWidget {
/* ... */
signals:
void someButtonPressed();
};class Output : public QGraphicsItem {
/* ... */
public:
void drawSomething();
};//somewhere:
Data* data = ...
Input* input = ...
Output* output = ...connect(input, &Input::someButtonPressed, data, &Data::setSomeData);
connect(data, &Data::someDataChanged, output, &Output::drawSomething);
@On top of these you could of course add any kind of CalculatorClass etc. that could access the data (to read and/or write).
Hope you will get some ideas from this to design a nice, modular app structure.