PyQt и MVC-паттерн - PullRequest
       18

PyQt и MVC-паттерн

30 голосов
/ 02 ноября 2009

Я пытаюсь спроектировать MVC-паттерн с PyQt. Я хочу разбить все программы на 3 части:

  1. классы, абстрагированные от всех классов Qt (модель)
  2. классы, предоставляющие данные из модели в приложение (контроллер) Qt
  3. само приложение Qt с определенным методом SignalsToSlots, который связывает сигналы с контроллером.

Это оптимально? Какая схема рекомендуется для использования в разработке PyQt?

Ответы [ 3 ]

42 голосов
/ 07 ноября 2009

Первое, что вы должны сделать, это использовать Qt4 designer для разработки вашего графического интерфейса и использовать pyuic4 для генерации вашего Python GUI. Это будет ваш взгляд, вы НИКОГДА не редактируете эти файлы python вручную. Всегда вносите изменения с помощью конструктора, это гарантирует, что ваш View будет отделен от вашей модели и элемента управления.

Для элемента управления создайте центральный класс, который наследуется от вашего базового графического виджета, такого как QMainWindow. Затем этот объект будет содержать пользовательский интерфейс, который является вашим сгенерированным объектом просмотра.

вот пример из учебника

ОБНОВЛЕНИЕ 2013: Вот более свежие уроки по PyQt и модели MVC Серия учебных пособий по PyQt MVC

import sys
from PyQt4 import QtCore, QtGui
from edytor import Ui_notepad

class StartQT4(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_notepad()
        self.ui.setupUi(self)


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = StartQT4()
    myapp.show()
    sys.exit(app.exec_())

Ключевым моментом в приведенном выше примере является то, что контроллер содержит пользовательский интерфейс и не наследует его напрямую. Контроллер будет отвечать за управление соединениями сигнальных слотов для вашего графического интерфейса и предоставление интерфейса для вашей модели данных.

Чтобы описать часть модели, нам нужен пример, давайте предположим, что ваш проект состоит в создании базы данных коллекции фильмов. Модель будет включать внутренние объекты, которые представляют отдельные фильмы, а также объекты, которые представляют списки фильмов. Вы управляете тем, что берете данные, введенные из вида, и ловите сигналы, затем проверяете их, прежде чем просить модель обновить себя. Эта часть имеет решающее значение, контроллер не должен напрямую обращаться к модели, если это вообще возможно, он должен запрашивать модель для доступа к себе.

Вот небольшой пример этого взаимодействия (непроверенный, возможно, некоторые опечатки):

class Movie():
    def __init__(self,title=None,year=None,genre=None):
        self.title=title
        self.year=year
        self.genre=genre
    def update(self,title=None,year=None,genre=None):
        self.title=title
        self.year=year
        self.genre=genre
    def to_xml(self,title=None,date=None,genre=None):
        pass #not implementing this for an example!

#when the controller tries to update it should use update function
movie1.update("Manos Hands Of Fate",1966,"Awesome")
#don't set by direct access, your controller shouldn't get that deep
movie1.title="Bad Idea" #do not want!

В MVC также важно централизовать доступ, например, пользователь может изменить заголовок, дважды щелкнув его на экране, или щелкнув по значку «Изменить» рядом с полем заголовка, оба этих интерфейсов должны завершиться используя тот же метод для изменения. И под этим я не подразумеваю, что каждый вызывает movie.update_title (title). Я имею в виду, что оба сигнала должны использовать один и тот же метод в контроллере.

Постарайтесь сделать все возможное, чтобы все отношения между View и контроллером были много к 1. Это означает, что у вас есть 5 способов что-то изменить в графическом интерфейсе, для этого есть 1 метод в контроллере. Если слоты не все совместимы, то создайте методы для каждого из методов, которые затем вызывают один единственный метод. Если вы решите проблему 5 раз для 5 стилей представления, то на самом деле нет и причины отделять представление от элемента управления. Кроме того, поскольку теперь у вас есть только один способ сделать что-то в контроллере, у вас хорошие отношения 1: 1 между элементом управления и моделью.

Поскольку ваша модель полностью отделена от Qt, в этом нет необходимости, и она может фактически осложнить вам жизнь. Использование таких вещей, как QStrings, в вашей модели может быть удобным, и если в другом приложении вы не хотите использовать накладные расходы на графическом интерфейсе, а хотите, чтобы модели просто импортировали только QtCore. Надеюсь, это поможет!

6 голосов
/ 07 ноября 2009

Да, PyQt использует концепцию Модель / Представление (официально без части «Контроллер»), но, возможно, у вас есть несколько искаженное представление о том, что это означает в PyQt.

Есть две части:

  1. Модели, подклассы из соответствующих базовых классов абстрактных моделей PyQt (QAbstractItemModel, QAbstractTableModel, QAbstractListModel и т. Д.). Эти модели могут напрямую взаимодействовать с вашими источниками данных (файлами, базами данных) или использовать ваши собственные PyQt-независимые модели, написанные ранее.
  2. Представления, которые реализованы в библиотеке Qt и часто не требуют каких-либо модификаций (примеры: QTreeView, QTableView и другие). Даже некоторые более простые элементы управления, такие как QComboBox, могут выступать в качестве представления для модели PyQt.

Все остальные части вашего приложения, которые реагируют на сигналы и т. Д., Могут рассматриваться как «Контроллер».

PyQt также предоставляет набор предопределенных «универсальных» моделей, которые можно разделить на подклассы или использовать напрямую, если вам нужны только простые функциональные возможности модели, такие как QStringListModel, QStandardItemModel и т. Д. И есть также модели, которые могут разговаривать напрямую к базам данных, например QSqlTableModel.

4 голосов
/ 24 июня 2015

Вот ссылка на официальное и подробное руководство о том, как архитектура Qt предлагает дизайн Model-View приложению

http://doc.qt.io/qt-5/model-view-programming.html

В Qt view и контроллер объединены, поэтому приложение может быть спроектировано с использованием Framework-View Framework.

Модель связывается с источником данных, предоставляя интерфейс для других компонентов в архитектуре. Природа связь зависит от типа источника данных и способа модель реализована. Представление получает модельные индексы из модели; это ссылки на элементы данных. Предоставляя модельные индексы модель, представление может получать элементы данных из источника данных. В стандартных представлениях делегат отображает элементы данных. Когда предмет редактируется, делегат общается с моделью напрямую, используя модельные индексы.

...

Модели, представления и делегаты взаимодействуют друг с другом, используя сигналы и слоты

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...