我上次使用桌面gui编程的主要经验是以mvvm方式使用c#/ wpf。我添加了一个可观察的集合,你不必在主线程上进行更改(它是通过在适当的时候使用锁定并在gui线程上运行来调用普通可观察集合的实例来实现的)。您可以在viewmodel中使用仅影响viewmodel的方法,而不是使用gui事件处理程序来浏览文件树。我非常喜欢这样一个事实:你可以大部分包含自己的gui代码,并且视图模型代码基本上是直接的,避免处理视图,除非通过更新状态和发送更改事件。
我正在使用pyqt 4.6构建一个小的自包含(如果可能的话没有依赖)应用程序(所以我不认为qml是可用的,同时qtwebkit似乎是在一个不同的包中,不是&#39 ; t安装在这些盒子上)。我有兴趣尝试以某种mvvm方式将数据与ui分开。
我可以将qt模型/视图(setModel)用于列表和树模型,但我不确定如何处理字符串/整数/其他值。该应用程序可能是相当静态的(中间没有消失的gui元素),但如果它变得更复杂(比如弹出窗口),我希望它不会因内存泄漏而崩溃或内存使用爆炸。我对python gc如何与信号/插槽以及qt的父/子内存清理进行交互有点不确定。
我写的应用程序很小,所以一个较小的自包含解决方案(可能不是通用/功能)或者我可以从中提取/复制代码的小型bsd / mit库将是首选。
到目前为止,这是我所拥有的,尽管如上所述,我有点不确定它的无错误。
#!/usr/bin/python
#
from __future__ import print_function
from PyQt4 import QtCore
from PyQt4 import QtGui
import sys
from time import sleep
def identity_function(x):
return x
def data_bind(model_get_prop, model_set_prop,
get_widget_prop, set_widget_prop,
model_prop_changed, window_prop_changed,
transform_func=identity_function,
transform_back_func=identity_function):
set_widget_prop(transform_func(model_get_prop()))
def set_m():
if model_get_prop() != get_widget_prop():
model_set_prop(transform_back_func(get_widget_prop()))
window_prop_changed.connect(set_m)
def set_w_prop():
if get_widget_prop() != model_get_prop():
set_widget_prop(transform_func(model_get_prop()))
model_prop_changed.connect(set_w_prop)
class ValueModel(QtCore.QObject):
model_changed = QtCore.pyqtSignal()
def __init__(self, value):
super(ValueModel, self).__init__()
self.__value = value
@property
def value(self):
return self.__value
@value.setter
def value(self, value):
if self.__value != value:
self.__value = value
self.model_changed.emit()
def gui_main():
app = QtGui.QApplication([])
s_model = ValueModel("yo")
w = QtGui.QWidget()
vbox = QtGui.QVBoxLayout()
t = QtGui.QTextEdit()
vbox.addWidget(t)
t2 = QtGui.QTextEdit()
vbox.addWidget(t2)
w.setLayout(vbox)
data_bind(lambda: s_model.value, lambda v: setattr(s_model, 'value', v), t.toPlainText, t.setPlainText, s_model.model_changed, t.textChanged)
data_bind(lambda: s_model.value, lambda v: setattr(s_model, 'value', v), t2.toPlainText, t2.setPlainText, s_model.model_changed, t2.textChanged)
l1 = QtGui.QLineEdit()
l2 = QtGui.QLineEdit()
lm1 = ValueModel(2)
lm2 = ValueModel(1)
vbox.addWidget(l1)
vbox.addWidget(l2)
lm1.model_changed.connect(lambda: print("l1 + l2 is " + str(lm1.value+lm2.value)))
lm2.model_changed.connect(lambda: print("l1 + l2 is " + str(lm1.value+lm2.value)))
data_bind(lambda: lm1.value, lambda v: setattr(lm1, 'value', v), l1.text, l1.setText, lm1.model_changed, l1.textChanged, str, int)
data_bind(lambda: lm2.value, lambda v: setattr(lm2, 'value', v), l2.text, l2.setText, lm2.model_changed, l2.textChanged, str, int)
w.show()
t.setText("a")
print(s_model.value)
sys.exit(app.exec_())
gui_main()
答案 0 :(得分:3)
我认为你想要的是QDataWidgetMapper
。
简而言之,它允许您将模型列的值映射到窗口小部件的显示属性(如标签或lineedit)。如果更新窗口小部件或模型中的值,则另一个将更新。
您还可以逐步浏览模型的行,这些行将所有映射的小部件更新为模型中下一行的内容(这可能超出您的需要,因此您只需要有一行模特)。
有关详细信息,请参阅Qt文档:http://qt-project.org/doc/qt-4.8/qdatawidgetmapper.html