MVC设计模式QT

MVC design pattern QT

我目前正在尝试实现 MVC 设计模式。我更喜欢模型和视图彼此独立以及与控制器独立的方法。如图所示。我知道这个话题之前已经讨论过,但根据研究,我仍然不完全确定我应该如何将我的视图连接到控制器以访问 ui 对象。我没有提供模型,因为目前它对我来说似乎很直接。请批评并给我改进策略。同样,我严格来说想使用 MVC 设计模式,而不是 Model/View。

main.cpp

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    View* view = new View();
    Model* model= new Model();
    Controller controller(view, model);
    controller->show();
    return a.exec();
}

View.h

namespace Ui {
    class View;
}

class View: public QMainWindow
{
    Q_OBJECT

public:
    View(QWidget *parent = Q_NULLPTR);
    ~View();
 
private:
    Ui::ViewClass *ui;
};

View.cpp

View::View(QWidget* parent)
    : QMainWindow(parent),
    ui(new Ui::ViewClass)
{
    ui->setupUi(this);
    setWindowTitle("MVC");
    ui->aDoubleSpinBox->setValue(0.0);
    ui->bDoubleSpinBox->setValue(0.0);
    ui->cDoubleSpinBox->setValue(0.0);
    ui->dDoubleSpinBox->setValue(0.0);

    ui->aDoubleSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
    ui->bDoubleSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
    ui->cDoubleSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
    ui->dDoubleSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);

}
View::~View()
{
    delete ui;
}

Controller.cpp

class Controller : public QObject
{
    Q_OBJECT

public:
    Controller(const View& view_, const Model& model, QObject* parent = Q_NULLPTR);

public slots:
    void setA(double a);
    void setB(double b);
    void setC(double c);
    void setD(double d);

signals:
    void eA(double value);
    void eB(double value);
    void eC(double value);
    void eD(double value);

private:
    std::unique_ptr<View> view;
    std::unique_ptr<Model> model;
};

Controller.cpp

Controller::Controller(const View& view_, const Model& model_, QObject* parent)
    : QObject(parent)
{
     view = std::make_unique<View>(view_);
     model = std::make_unique<Model>(model_);

     // Here is where I am not sure how to access the ui object since it is private.
     // Do I create a public function in the View class? For eg...
     // QDoubleSpinBox* getADoubleSpinBox() { return *ui.aDoubleSpinBox; }
     

     //connect(view-> , QOverload<double>::of(&QDoubleSpinBox::valueChanged, this, 
     //&Controller::setA);


     connect(this, &Controller::eA, model.get(), &Model::setA);
     connect(this, &Controller::eB, model.get(), &Model::setB);
     connect(this, &Controller::eC, model.get(), &Model::setC);
     connect(this, &Controller::eD, model.get(), &Model::setD);   
}

void Controller::setA(double a)
{
    emit eA(a);
}

void Controller::setB(double b)
{
    emit eB(b);
}

void Controller::setC(double c)
{
    emit eC(c);
}

void Controller::setD(double d)
{
    emit eD(d);
}

一个典型的解决方案是,视图使用 Q_PROPERTY(设置、获取和通知)公开数据成员。 View 根本不需要知道控制器。 View是controller拥有的独立对象

对于一个旋转框,视图声明可以是

namespace Ui {
    class View;
}

class View: public QMainWindow
{
    Q_OBJECT
    Q_PROPERTY(double a READ a WRITE setA NOTIFY aChanged)
public:
    View(QWidget *parent = Q_NULLPTR)
    ~View();
    double a();
    void setA(double val);
    
 signals:
    void aChanged();

private:

    Ui::ViewClass *ui;
};

而视图定义可以是,

double View::a()
{
    return  ui->aDoubleSpinBox->value();
}

void View::setA(double val)
{
     ui->aDoubleSpinBox->setValue(val);
}

View::View(QWidget* parent)
: QMainWindow(parent),
ui(new Ui::ViewClass)
{
    ui->setupUi(this);
    setWindowTitle("MVC");
    connect(ui->aDoubleSpinBox, &QDoubleSpinBox::valueChanged, [&](double) {
        emit aChanged();
    });
}

控制器应将视图通知信号连接到其 setter。当它想改变视图数据时,它应该调用setter方法。

这样,视图只负责显示数据和用户交互,控制器负责修改数据和获取更新。