Форум программистов, компьютерный форум, киберфорум
Наши страницы

Qt

Войти
Регистрация
Восстановить пароль
 
 
Bretbas
Каждому свое
363 / 133 / 34
Регистрация: 05.08.2013
Сообщений: 1,414
Завершенные тесты: 1
#1

MVVM в QT. Реально ли в данное время? - C++ Qt

11.01.2018, 17:28. Просмотров 418. Ответов 23
Метки нет (Все метки)

Привет всем. Интересует вопрос. Насколько продуктивно на данном этапе времени используют архитектурный паттерн MVVM в QT? Можно ли привязывать свойства из ViewModel к свойствам контролов? На сколько это практично? Как обстоит дело с командами, которые будут вызываться со стороны View?
Вообще, кто-нибудь использует в QT паттерн MVVM для разработки приложений?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.01.2018, 17:28
Здравствуйте! Я подобрал для вас темы с ответами на вопрос MVVM в QT. Реально ли в данное время? (C++ Qt):

Действительно ли java на данное время самый актуальный язык? - Java
нужен совет профессионалов.действительно ли java на данное время самый актуальный язык?на нем все пишется от сайтов до игр.с чего начать...

За какое минимальное время роботы смогут обработать данное количество деталей? - C++
Всем добрый вечер. Есть такая задача: На некотором заводе решили модернизировать производство и закупили для этого роботов. Так как для...

Рассчитать время, при котором данное количество вещества вступит в реакцию - Химия
Ребят подсобите пожалуйста. Без понятия как делать. 2) При температуре 10C некоторое количество вещества вступает в реакцию за 2 ч....

Рассчитать время, за которое катер пройдёт данное расстояние против течения и по течению - Pascal
Разработать, ввести в ЭВМ и отладить программу для расчёта времени, за которое катер пройдёт данное расстояние против течения и по течению,...

Найти заряд, протекший по соленоиду за данное время при замыкании витков соленоида сопротивлением - Электричество и магнетизм
В магнитном поле с индукцией, изменяющейся со скоростью 4 млТл/с, находится со- леноид. Ось соленоида с вектором магнитной индукции...

Команда или макрокоманда "УдалитьЗапись" в данное время недоступна - MS Access
Подскажите пожалуйста, как решить проблему! Создала базу данных, и при проверке обнаружилась ошибка. В форме ВидыСтрахованияСписок, она...

23
TRam_
486 / 492 / 134
Регистрация: 14.05.2017
Сообщений: 1,689
11.01.2018, 18:49 #2
Для Qt, при использовании сигналов-слотов, более рациональным будет MVP, чем MVVM. В представителе (обычно он же является классом окна или диалога) реализуется создание и разрушение связей между видом (базовым виджетом окна, в котором в public'е доступны все виджеты) и моделью.

Добавлено через 10 минут
А если речь вообще о моделях, то есть QAbstractItemModel и QAbstractTableModel + куча зависимых от них, и специализированные виждеты для работы с такими моделями (QTableView, QListView, QTreeView ...). Одно у другому подключается одним вызовом, наподобие
C++ (Qt)
1
treeView1->setModel(&mymodel1);
и эта связь уже будет работать в обе стороны (как редактирование в виджете, так и обновление в модели)

Добавлено через 23 минуты
А по поводу QML - https://habrahabr.ru/post/302428/
2
Digital_Cry
Заблокирован
11.01.2018, 19:50 #3
паттерны... ох уж эти паттерны... подобными словами бросаются только студенты и преподы на экзаменах, в реальности в продакшене каждый пишет как хочет, по своему и в зависимости от ситуации
0
Bretbas
Каждому свое
363 / 133 / 34
Регистрация: 05.08.2013
Сообщений: 1,414
Завершенные тесты: 1
11.01.2018, 20:16  [ТС] #4
TRam_,
Цитата Сообщение от TRam_ Посмотреть сообщение
Для Qt, при использовании сигналов-слотов, более рациональным будет MVP, чем MVVM. В представителе (обычно он же является классом окна или диалога) реализуется создание и разрушение связей между видом (базовым виджетом окна, в котором в public'е доступны все виджеты) и моделью.
чем это отличается от просто событийно-управляемого подхода? Все грубо говоря в code-behind.

Цитата Сообщение от TRam_ Посмотреть сообщение
А если речь вообще о моделях, то есть QAbstractItemModel и QAbstractTableModel + куча зависимых от них, и специализированные виждеты для работы с такими моделями (QTableView, QListView, QTreeView ...). Одно у другому подключается одним вызовом, наподобие
C++ (Qt)
1
treeView1->setModel(&mymodel1);
Так, ну это уже на что-то более менее похоже. А как свойства связываются у контролов с "свойствами"(или как они там будут называться) в модели? Или там как-то все по другому?

Добавлено через 1 минуту
Digital_Cry, Ну не скажи. Вопрос на сколько ты изучил разные подходы к решению определенных задач. Я, например, пока учусь, стараюсь брать реальные задачи, и выполнить их как можно более правильно. Как только выйду на свободу, думаю эти знания пригодятся

Добавлено через 19 минут
TRam_, А что Вы скажете по поводу этого http://antyadev.blogspot.ru/2012/07/mvvm-with-qt-quick.html
0
TRam_
486 / 492 / 134
Регистрация: 14.05.2017
Сообщений: 1,689
11.01.2018, 20:20 #5
Цитата Сообщение от Bretbas Посмотреть сообщение
TRam_, А что Вы скажете по поводу этого
Более подробно об этом же (о QML) - в разных частях той статьи, что по ссылке в моём посте.
1
Bretbas
Каждому свое
363 / 133 / 34
Регистрация: 05.08.2013
Сообщений: 1,414
Завершенные тесты: 1
11.01.2018, 20:33  [ТС] #6
TRam_, Блин, там как-то все сложно написано. Я так понял, он делает какой-то мини-фреймфорк, для того, чтобы в QML иметь доступ к данным модели? Если честно, я половину не понял, что он имел ввиду
0
TRam_
486 / 492 / 134
Регистрация: 14.05.2017
Сообщений: 1,689
11.01.2018, 20:34 #7
Если делать без QML, то связывание будет состоять из соединения сигналов-слотов. Ну например для того, чтобы обновлять состояние QLineEdit'а, нужно объявить в модели некий сигнал, а в представителе соединить его со слотом void setText(const QString &) ( http://doc.qt.io/qt-5/qlineedit.html#text-prop ) . Для обратного (реакции на изменение пользователем) в модели объявить слот обработки строки из QLineEdit'а, а в представителе - связать его с сигналом void QLineEdit::textEdited(const QString &text) .
0
Bretbas
Каждому свое
363 / 133 / 34
Регистрация: 05.08.2013
Сообщений: 1,414
Завершенные тесты: 1
12.01.2018, 20:43  [ТС] #8
TRam_, ну это то все вроде бы понятно

Добавлено через 23 часа 58 минут
TRam_, Блин, я все таки не могу понять, как правильнее сделать. Подскажи пожалуйста.

Вот я написал небольшую программку на MVVM: 3 поля ввода - Имя, Фамилия, Возраст. По нажатию на кнопку, нужно отобразить Имя, Фамилию и возраст в одной строке в контроле Text. Для решение поставленной задачи, сделал MainViewModel( Для упрощения примера, данные внес прям в VM ):
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class WindowViewModel : public QObject
{
    Q_OBJECT
public:
    explicit WindowViewModel(QObject *parent = nullptr);
 
    // Properties
    Q_PROPERTY(QString Name READ getName WRITE setName NOTIFY NameChanged)
    Q_PROPERTY(QString Surname READ getSurname WRITE setSurname NOTIFY SurnameChanged)
    Q_PROPERTY(int Age READ getAge WRITE setAge NOTIFY AgeChanged)
    Q_PROPERTY(QString Result READ getResult WRITE setResult NOTIFY ResultChanged)
 
    // Commands
    Q_INVOKABLE void command()
    {
        QString Age = QString::fromStdString(std :: to_string(_age));
        setResult(_name + " " + _surname + " " + Age);
    }
 
    // Getters/Setters
    inline QString  getName()
    {
        return _name;
    }
    inline void     setName(const QString& name)
    {
        _name = name;
        emit NameChanged();
    }
 
    inline QString  getSurname()
    {
        return _surname;
    }
    inline void     setSurname(const QString& surname)
    {
        _surname = surname;
        emit SurnameChanged();
    }
 
    inline int      getAge()
    {
        return _age;
    }
    inline void     setAge(const int& age)
    {
        _age = age;
        emit AgeChanged();
    }
 
    inline QString  getResult()
    {
        return _result;
    }
    inline void     setResult(const QString& result)
    {
        _result = result;
        emit ResultChanged();
    }
 
 
signals:
    void NameChanged();
    void SurnameChanged();
    void AgeChanged();
    void ResultChanged();
 
public slots:
 
private:
    QString _name;
    QString _surname;
    int     _age;
    QString _result;
};
Затем создал окно, добавил компоновку Column, ввел 3 TextInput'а, кнопку и контрол Text. Затем все подвязал между собой:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    Column {
        id: column
        anchors.horizontalCenter: parent.horizontalCenter
    
        TextEdit {
            
            id: nameInput
            font.pixelSize: 12
    
            text: model.Name
            Binding { target: model; property: "Name"; value: nameInput.text }
        }
    
        TextEdit {
            id: surnameInput
            font.pixelSize: 12
    
            text: model.Surname
            Binding { target: model; property: "Surname"; value: surnameInput.text }
        }
    
        TextEdit {
            id: ageInput
            font.pixelSize: 12
    
            text: model.Age
            Binding { target: model; property: "Age"; value: ageInput.text }
        }
    
        Rectangle
        {
            width: 100
            height:20
            color:"Red"
    
            Text
            {
                anchors.centerIn: parent
                text: "моя кнопка"
            }
    
            MouseArea
            {
                anchors.fill: parent
                onClicked: model.command()
            }
        }
    
        Text
        {
            id: result
            width:200
            height:30
            color: "Green"
            text: model.Result
        }
    
}
Ну и в main.cpp определил у главного контекста новое свойство modelи задал его как MainViewModel:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
int main(int argc, char *argv[])
{
...
    QQmlApplicationEngine engine;
    auto rootContext = engine.rootContext();
    rootContext -> setContextProperty( "model", new WindowViewModel());
 
...
    return app.exec();
}
Все работает. Все замечательно.

Интересуют вопросы:
1. Чем такой вариант плох?
2. Можно ли избавиться от такого ужасного объявления свойств? Хотя бы чтобы не задавать эти getters/setters?
3. Если есть у кого-нибудь свободные 10 минут, покажите как сделать этот же пример, только с более культурным подходом, которые используют на QT
0
alexu_007
126 / 136 / 29
Регистрация: 29.05.2015
Сообщений: 989
13.01.2018, 10:46 #9
Main.cpp
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <QtGui/QApplication>
#include "widget.h"
#include <QTextCodec>
 
int main(int argc, char *argv[])
{
 
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("cp1251"));
 
    QApplication a(argc, argv);
    Widget w;
    w.show();
    
    return a.exec();
}
widget.h
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
    
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    
private:
    Ui::Widget *ui;
 
public slots:
    void text_changed();
    void press_pbtn_01();
};
 
#endif // WIDGET_H
widget.cpp
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "widget.h"
#include "ui_widget.h"
 
 
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    QObject::connect(ui->lineEdit_1, SIGNAL(textChanged(QString)), this, SLOT(text_changed()));
    QObject::connect(ui->lineEdit_2, SIGNAL(textChanged(QString)), this, SLOT(text_changed()));
    QObject::connect(ui->lineEdit_3, SIGNAL(textChanged(QString)), this, SLOT(text_changed()));
 
    QObject::connect(ui->pbtn_01, SIGNAL(clicked()), this, SLOT(press_pbtn_01()));
}
 
 
 
Widget::~Widget()
{
    delete ui;
}
 
 
 
void Widget::text_changed()
{
    QString str1 = ui->lineEdit_1->text();
    QString str2 = ui->lineEdit_2->text();
    QString str3 = ui->lineEdit_3->text();
 
    if((str1 != "")&&(str2 != "")&&(str3 != "")) ui->pbtn_01->setEnabled(true);
    else ui->pbtn_01->setEnabled(false);
}
 
 
 
 
void Widget::press_pbtn_01()
{
    QString str = ui->lineEdit_1->text() + " " +
                        ui->lineEdit_2->text() + " " +
                            ui->lineEdit_3->text();
 
    ui->label_4->setText(str);
}
0
Миниатюры
MVVM в QT. Реально ли в данное время?  
Bretbas
Каждому свое
363 / 133 / 34
Регистрация: 05.08.2013
Сообщений: 1,414
Завершенные тесты: 1
13.01.2018, 11:12  [ТС] #10
alexu_007, Вы наверное не поняли что я хотел увидеть. Я хотел увидеть правильное разделение Представления от Модели. Например в платформе .Net, есть такая технология, которая похожа на QT quick, называется она WPF. Эта технология позволяет разделить декларативное описания UI от логики приложения. Так как в WPF присутствовали "привязки данных", то замечательным решением написания десктопных приложений, было использования паттерна MVVM, который является выродком от нашего любимого MVC. Так вот, писал я, писал на WPF + MVVM. Тут вздумал перейти на QT. Увидел QT Quick, QML, и все такое...обрадовался, подумал, что можно будет писать все также, как я писал на WPF. Но не тут то было...
Моя попытка реализации программы, которую я написал выше, с использованием MVVM подхода на QT Quick, не дала хороших результатов:
Во-первых, свойства...да, в C++ их нет, но вот эти страшные подобные "свойства", которые предоставляет мне QT, никуда не годятся. А, увы, в MVVM без свойств никуда.
Во-вторых, какие-то страшные привязки в QML, по сравнению с XAML. Попахивает костылями.
В-третьих, все говорят, что в QT не применяется MVVM, нужно использовать что-то другое. Но что? Написали что MVP. Вот я бы хотел услышать вариант той же программы, только с тем подходом, который применяется чаще всего на QT, и будет соответствовать естественному отделению Представления от Модели

Тот вариант, который Вы написали, никуда не годиться. Слишком тесная связь между View и Model. Это обычных событийно-управляемый подход - все пишем в Code-Behind, и все будет здорово. Нет...так не пойдет. Я уже с этим сталкивался, больше не хочу
0
Digital_Cry
Заблокирован
13.01.2018, 11:17 #11
Цитата Сообщение от Bretbas Посмотреть сообщение
. Я хотел увидеть правильное разделение Представления от Модели
QML - это уже разделение как ты выразился модели от данных. Модель на C++, отображение на QML

Давай в двух словах, чего тебе нужно, лень читать весь блок сверху

Эй Кот, приём
0
Bretbas
Каждому свое
363 / 133 / 34
Регистрация: 05.08.2013
Сообщений: 1,414
Завершенные тесты: 1
13.01.2018, 11:33  [ТС] #12
Digital_Cry,
Цитата Сообщение от Digital_Cry Посмотреть сообщение
QML - это уже разделение как ты выразился модели от данных. Модель на C++, отображение на QML
Я согласен. Но если приложение большое, нужно этим разделением уметь пользоваться. Но благо, что люди уже за нас подумали, и ввели архитектурные паттерны, которые решают эту проблему

Цитата Сообщение от Digital_Cry Посмотреть сообщение
Давай в двух словах, чего тебе нужно
Мне нужно научиться писать кроссплатформенные приложения
0
Digital_Cry
Заблокирован
13.01.2018, 11:50 #13
Цитата Сообщение от Bretbas Посмотреть сообщение
Но благо, что люди уже за нас подумали, и ввели архитектурные паттерны, которые решают эту проблему
когда перейдёшь от проектирования сферического коня в вакууме и перейдёшь к коммерческой разработке, все эти глупости отпадут сами собой )
Цитата Сообщение от Bretbas Посмотреть сообщение
Мне нужно научиться писать кроссплатформенные приложения
Ты их уже пишешь, установив Qt, если конечно в коде ты не добавляешь #include <windows.h>
0
Bretbas
Каждому свое
363 / 133 / 34
Регистрация: 05.08.2013
Сообщений: 1,414
Завершенные тесты: 1
13.01.2018, 11:55  [ТС] #14
Digital_Cry,
Цитата Сообщение от Digital_Cry Посмотреть сообщение
когда перейдёшь от проектирования сферического коня в вакууме и перейдёшь к коммерческой разработке, все эти глупости отпадут сами собой )
Что ты предлагаешь? Где я нахожусь, пока не приступить к коммерческой разработки
0
alexu_007
126 / 136 / 29
Регистрация: 29.05.2015
Сообщений: 989
13.01.2018, 12:09 #15
Цитата Сообщение от Bretbas Посмотреть сообщение
3 поля ввода - Имя, Фамилия, Возраст. По нажатию на кнопку, нужно отобразить Имя, Фамилию и возраст в одной строке в контроле Text.
Я так и сделал. Плюс добавил, чтобы нельзя было вывести в строку, пока все 3 поля не заполнены. Это бонус от меня. Какая задача, такое и решение.
0
13.01.2018, 12:09
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.01.2018, 12:09
Привет! Вот еще темы с ответами:

Команда или макрокоманда "Обновить" в данное время недоступна - MS Access
При нажатие кнопки на форме обновить даные выскакивает ошибка &quot;Команда или макрокоманда &quot;Обновить&quot; в данное время недоступна &quot; что...

Ошибка "файл используется в данное время" - C#
FileInfo f = new FileInfo(&quot;d:\\Mytext.txt&quot;); if (f.Exists == false) { f.Create(); ...

К четным элементам целочисленного массива прибавить данное число а, а из элементов с четными номерами вычесть данное число b. - C++
К четным элементам целочисленного массива прибавить данное число а, а из элементов с четными номерами вычесть данное число b.

Run-time error 2046: "Команда "Применить фильтр" в данное время недоступна"(ACCESS 2007) - MS Access
Всем привет! При старте программы запускается форма с таблицей, в процедуре открытия формы такие строки: private sub...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.