2009-11-02 92 views
26

Por favor, ayúdenme a diseñar el patrón MVC con PyQt. Quiero dividir todos los programas en 3 partes:PyQt y patrón MVC

  1. alguna clase que se abstrae de todas las clases Qt (modelo)
  2. alguna clase que proporciona datos de modelo a QT-aplicación (controlador)
  3. Qt -app en sí mismo con el método definido SignalsToSlots que conecta señales con el controlador.

¿Es óptimo y qué esquema se utiliza en el desarrollo de PyQt?

P.S .: Lo siento por mi Inglés =)

Respuesta

38

Una de las primeras cosas que debe hacer es utilizar el diseñador Qt4 para diseñar su interfaz gráfica de usuario y utilizar pyuic4 para generar su interfaz gráfica de usuario pitón. Esta será su opinión, NUNCA edita estos archivos de Python a mano. Siempre realice cambios utilizando el diseñador, esto garantiza que su Vista esté separada de su modelo y control.

Para el elemento de control, cree una clase central que herede de su widget gui base como QMainWindow. Este objeto tendrá entonces contiene ui miembro que es el objeto de vista que acaba de generar.

aquí es un ejemplo de a tutorial

ACTUALIZACIÓN 2013: Aquí hay un tutorial (s) más reciente sobre PyQt y MVC Modelo PyQt MVC Tutorial Series

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_()) 

El punto clave en el ejemplo anterior es el controlador contiene el ui y no lo hereda directamente. El controlador será responsable de gestionar las conexiones de ranuras de señal para su interfaz gráfica de usuario y proporcionar una interfaz para su modelo de datos.

Para describir la parte del modelo, necesitamos un ejemplo, supongamos que su proyecto es crear una base de datos de colecciones de películas. El modelo incluiría los objetos internos que representan películas individuales, junto con objetos que representan listas de películas. Su control tomaría los datos ingresados ​​desde la vista y captaría las señales, luego las validaría antes de pedirle al modelo que se actualice a sí mismo. Esa parte es crucial, el controlador no debe acceder directamente al modelo si es posible, debe pedirle al modelo que acceda a él.

Aquí es un pequeño ejemplo de esta interacción (no probado, puede haber algunos errores tipográficos):

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! 

También es importante en la MVC para centralizar el acceso, por ejemplo, el usuario puede cambiar el título haciendo doble clic en él en la pantalla, o haga clic en editar al lado del campo de título, ambos de esas interfaces deben terminar usando el mismo método para el cambio. Y con esto no quiero decir que cada uno llame movie.update_title (title). Quiero decir que ambas señales deberían usar el mismo método en el controlador.

Intente tanto como sea posible para que todas las relaciones entre la Vista y el controlador sean varias. Esto significa que tiene 5 formas de cambiar algo en la interfaz gráfica de usuario, tiene 1 método en el controlador para manejar esto. Si las ranuras no son todas compatibles, cree métodos para cada uno de los métodos que luego llamen a un único método. Si resuelve el problema 5 veces para 5 estilos de vista, entonces realmente no hay razón para separar la vista del control.Además, dado que ahora solo tiene una forma de hacer algo en el controlador, tiene una buena relación de 1 a 1 entre el control y el modelo.

En cuanto a tener su modelo completamente separado de Qt, eso no es realmente necesario y en realidad puede hacer la vida más difícil para usted. Usar cosas como QStrings en tu modelo puede ser conveniente, y si en otra aplicación no quieres la sobrecarga de una Gui pero quieres que los modelos solo importen QtCore. ¡Espero que esto ayude!

+1

1, 'no establezca mediante acceso directo, el controlador shouldn' t get that deep': ¿por qué no mencionar la posibilidad de 'self._title = title; self._year = año; ... '? – mlvljr

+0

¿Por qué la edición manual de su vista hace que no esté separada de su modelo y control? – Kemeia

+0

No lo causa, pero no lo hace ** ** lo previene – cmaynard

6

Sí, PyQt usa el concepto de Modelo/Vista (oficialmente sin la parte "Controlador"), pero puede que tengas una imagen algo distorsionada, ¿qué significa en PyQt?

Hay dos partes:

  1. Modelos, una subclase de base de clases apropiadas PyQt abstractas modelo (QAbstractItemModel, QAbstractTableModel, QAbstractListModel, etc.). Estos modelos pueden comunicarse directamente con sus fuentes de datos (archivos, bases de datos) o usar sus propios modelos PyQt-agnósticos escritos anteriormente.
  2. Vistas, que se implementan en la biblioteca Qt, y con frecuencia no requieren ninguna modificación (ejemplos: QTreeView, QTableView y otros). Incluso algunos controles más simples, como QComboBox, pueden actuar como una vista para un modelo PyQt.

Todas las demás partes de su aplicación, que reaccionan a señales, etc. pueden considerarse como "Controlador".

PyQt también proporciona un conjunto de modelos predefinidos "universales" que puede tener subclases o utilizados directamente si necesita solamente una funcionalidad simple del modelo, al igual QStringListModel, QStandardItemModel, etc., y también hay modelos que pueden hablar directamente a las bases de datos , como QSqlTableModel.

+1

Tenga en cuenta que el marco Modelo/Vista en Qt está restringido a tablas recursivas (aunque las vistas admiten principalmente listas, filas, tablas y filas recursivas (árbol)). Es posible crear aplicaciones MVC genéricas en PyQt/Qt que no utiliza Qt's ModelView-framework, si sus datos tienen una estructura diferente. (En mi humilde opinión, forzar cosas en ModelView de Qt no siempre es la mejor idea ...) – Macke

+0

de hecho ~ Todavía no entiendo la idea real del modelo/marco de visión de Qt sin controlador. – Drake

+0

Mejora la reutilización de código. Es bastante común cuando utiliza exactamente la misma clase de modelo o incluso instancia con diferentes vistas (por ejemplo, con QTreeView en una ventana de diálogo y con QComboBox en otra). – abbot

2

Aquí hay un enlace a la guía oficial y detallada sobre cómo la arquitectura de Qt ofrece Modelo-Vista de diseño de una aplicación

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

En Qt, la vista y el controlador se combinan, por lo tanto, una aplicación puede diseñarse utilizando Modelo-Vista marco.

El modelo se comunica con una fuente de datos, proporcionando una interfaz para los demás componentes de la arquitectura. La naturaleza de la comunicación depende del tipo de fuente de datos y de cómo se implementa el modelo . La vista obtiene índices de modelo del modelo; estas son referencias a elementos de datos. Al proporcionar índices de modelo a el modelo, la vista puede recuperar elementos de datos de la fuente de datos. En vistas estándar, un delegado representa los elementos de datos. Cuando se edita un elemento , el delegado se comunica directamente con el modelo utilizando los índices del modelo .

...

modelos, vistas y los delegados se comunican entre sí mediante señales y ranuras