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方法。
这样,视图只负责显示数据和用户交互,控制器负责修改数据和获取更新。
我目前正在尝试实现 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方法。
这样,视图只负责显示数据和用户交互,控制器负责修改数据和获取更新。