Ответ 1
Одна из первых вещей, которую вы должны сделать, это использовать конструктор Qt4 для разработки своего gui и использовать pyuic4 для создания вашего графического интерфейса python. Это будет ваше мнение, вы НИКОГДА не отредактируете эти файлы python вручную. Всегда вносите изменения с помощью конструктора, это гарантирует, что ваш вид отделен от вашей модели и управления.
Для элемента управления создайте центральный класс, который наследуется от вашего базового виджета gui, такого как QMainWindow. Этот объект будет содержать член ui, который вы только что создали.
вот пример из учебника
UPDATE 2013: Вот более свежие учения по PyQt и MVC Model Учебная серия 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_())
Ключевым моментом в приведенном выше примере является то, что контроллер содержит ui и не наследует его напрямую. Контроллер будет отвечать за управление соединениями слотов сигналов для вашего gui и предоставление интерфейса для вашей модели данных.
Чтобы описать часть модели, нам нужен пример, давайте предположим, что ваш проект состоит в создании базы данных коллекции фильмов. Модель будет включать в себя внутренние объекты, которые представляют отдельные фильмы, а также объекты, представляющие списки фильмов. Вы контролируете данные, введенные из представления, и поймаете сигналы, а затем подтвердите их, прежде чем запрашивать модель для обновления. Эта часть имеет решающее значение, контроллер не должен напрямую обращаться к модели, если это вообще возможно, она должна попросить модель получить доступ к ней.
Вот небольшой пример этого взаимодействия (непроверенный, может быть, некоторые опечатки):
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 (название). Я имею в виду, что оба сигнала должны использовать один и тот же метод в контроллере.
Попробуйте как можно больше, чтобы все отношения между View и контроллером были много с 1. Значение, то есть у вас есть 5 способов изменить что-то в gui, у вас есть 1 метод в контроллере. Если слоты не все совместимы, чем создавать методы для каждого из методов, которые затем вызывают один единственный метод. Если вы решите проблему 5 раз для 5 стилей представления, то действительно нет и причины отделить представление от элемента управления. Кроме того, поскольку теперь у вас есть только один способ сделать что-то в контроллере, у вас есть приятная связь 1:1 между элементом управления и моделью.
Что касается того, что ваша модель полностью отделена от Qt, это на самом деле не обязательно и может на самом деле сделать жизнь сложнее для вас. Использование таких вещей, как QStrings в вашей модели, может быть удобным, и если в другом приложении вы не хотите накладных расходов на Gui, но хотите, чтобы модели просто импортировали только QtCore. Надеюсь, это поможет!