我一直在尝试找到一种用 PySide 实现 MVVM 的方法,但一直未能成功。我认为应该有一种方法可以使用 QItemEditorFactory 从 ViewModels 创建视图,并且可以使用 QDataWidgetMapper 进行数据绑定。
您对如何使用 Qt 和 PySide 实现 MVVM 有什么想法吗?即使有一些 C++ 资源,我也会尝试将它们翻译成 python。
谢谢。
MVVM 是 MVP(模型-视图-演示者)模式的特化,并不是 WPF 特有的,但它是其诞生的一部分。我认为您想要获得的是一个 MVP,将您的域模型公开为该域的视图。
如果您想要 C++ 中的示例,您可以查看 此 PDF。 但是,您可以从下面的 manged c# 中的简洁概要中了解其要点:
public class DomainView : IDomainView
{
private IDomainPresenter domainPresenter = null;
///<summary>Constructor</summary>
public DomainView()
{
domainPresenter = new ConcreteDomainPresenter(this);
}
}
另外,我想知道您可以使用抽象对象表示法来从模型到视图创建可传递的泛型(视图模型)。基本上,您需要一个中间函数来标记要序列化的相关部分。
我不知道你想将 MVVM 发展到什么程度,但在基础层面上它是 Qt 附带的,而且我已经使用它很长时间了。您有一个特定于业务的模型,例如与数据库绑定的模型。然后,您创建特定于视图的视图模型作为代理模型。您可以根据需要堆叠几层。然后您使用视图来展示它。只要一切设置正确,它就会“正常工作”。现在,如果您想使用模型来配置视图,Qt 不会直接为您提供任何内容。您需要编写一个工厂类,它可以使用视图模型数据来实例化和设置视图。一切都取决于您想要走多远,以及它给您带来什么架构优势。
简单的例子:
型号#1
from models.event import Event
class Event_Container:
def __init__(self):
self.events = []
def create_new_event(self, name):
if name:
self.events.append(Event(name))
def get_events_str(self):
result = []
for event in self.events:
result.append(event.name)
return result
型号#2
class Event:
def __init__(self, name):
self.name = name
视图模型#1
import tkinter as tk
from views.new_event_view import New_event_view
from models.event_conteiner import Event_Container
class App_vm:
def __init__(self):
self.model = Event_Container()
self.events = tk.Variable(value=[])
def create_new_event(self):
New_event_view(self, self.model)
def update_list_events(self):
self.events.set(self.model.get_events_str())
视图模型#2
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from models.event_conteiner import Event_Container
from viewmodels.app_vm import App_vm
class New_event_vm:
def __init__(self, master_vm: App_vm, master_m: Event_Container):
self.master_vm = master_vm
self.master_m = master_m
def create_new_event(self, name):
self.master_m.create_new_event(name)
self.master_vm.update_list_events()
查看#1
import tkinter as tk
from viewmodels.app_vm import App_vm
class App_view(tk.Frame):
def __init__(self, root):
super().__init__(root)
self.vm = App_vm()
self.create_widget()
def create_widget(self):
self.create_new_event_btn = tk.Button(
text="Create new event", command=self.create_new_event
)
self.create_new_event_btn.pack()
self.name_event_list = tk.Listbox(listvariable=self.vm.events)
self.name_event_list.pack(fill=tk.BOTH)
def create_new_event(self):
self.vm.create_new_event()
查看#2
import tkinter as tk
from viewmodels.new_event_vm import New_event_vm
class New_event_view(tk.Frame):
def __init__(self, app_vm: App_vm, app_model: Event_Container):
self.root = tk.Tk()
self.root.geometry("200x200")
super().__init__(self.root)
self.vm = New_event_vm(app_vm, app_model)
self.create_widget()
def create_widget(self):
self.name_event_entry = tk.Entry(self.root)
self.name_event_entry.pack()
self.create_new_event_btn = tk.Button(
self.root, text="Create new event", command=self.create_new_event
)
self.create_new_event_btn.pack()
def create_new_event(self):
name_event = self.name_event_entry.get()
self.vm.create_new_event(name_event)
主要:
import tkinter as tk
from views.app_view import App_view
root = tk.Tk()
root.geometry("400x400")
app = App_view(root)
root.mainloop()
对我来说,一个明显的答案是,MVVM 适用于 WPF 和其他一些欢迎这种模式的技术,因此您必须找出是否可以将此模式应用于其他技术。请阅读 wiki 中的 MVVM。