OOOview와 OOOmodel의 개념으로 지원되는 위젯들은 데이터 전파가 잘되나, 일반 위젯은 뷰-모델의 개념이 없기 때문에 유사한 흉내를 내주기 위해서는 모델을 하나 만들고QDataWidgetMapper로 각각의 위젯과 연결을 해줌으로써 MVVM 패턴을 적용할 수 있을것으로 생각된다.
LineEdit, DateTime, TextEdit 은 매핑한 후 뷰와 모델간 데이터 변경 전달이 자동으로 잘되지만,
ComboBox의 경우 QDataWidgetMapper에서 currentIndex property로 매핑한 경우 상호간 변경내용 전파가 잘되나, currentText로 매핑할 경우 뷰->모델로는 전파가 되나, 모델->뷰로는 전파가 잘 되지 않는다.
이 문제를 해결하기위해 QComboBox를 상속하여 MyComboBox를 만들었다
테스트 화면을 보면 뷰-뷰모델간 동기화를 위한 별도의 코드없이 매핑만으로 같은 모델을 공유하는 두개의 윈도우간 데이터의 변경결과가 자동 반영되는 것을 알 수 있다.
- MyComboBox.py
#-*- coding: utf-8 -*-
from PySide.QtGui import QComboBox
from PySide.QtCore import Property, Qt
class MyComboBox(QComboBox):
def __init__(self, params=None):
super().__init__(params)
def set(self, text):
''' 텍스트 값을 설정하면 현재 인덱스 값을 텍스트와 일치하는 인덱스로 변경
'''
self.setCurrentIndex(self.findText(text, Qt.MatchExactly))
def get(self):
return self.currentText()
''' get을 읽기, set을 쓰기 property로 등록
'''
text = Property(str, get, set)
테스트를 위해 회원 등록하는 간단한 GUI의 뷰와 뷰모델은 다음과 같다
- MemberV.py
import sys
from PySide.QtGui import QWidget, QApplication, QDataWidgetMapper
from Ui_member import Ui_member
from src.mvvmTest.MemberVm import MemberVm
class MemberV(QWidget):
'''
classdocs
'''
def __init__(self, params=None):
'''
Constructor
'''
super().__init__()
self.ui = Ui_member()
self.ui.setupUi(self)
self.initCombo()
self.vm = params
self.bind()
self.show()
def initCombo(self):
self.ui.comboBoxDept.addItems("월화수목금토일")
self.ui.comboBoxUsage.addItems("ox")
def bind(self):
self.mapper = QDataWidgetMapper()
self.mapper.setModel(self.vm.model)
self.mapper.addMapping(self.ui.lineEditId, 0)
self.mapper.addMapping(self.ui.lineEditName, 1)
self.mapper.addMapping(self.ui.lineEditPwd, 2)
self.mapper.addMapping(self.ui.lineEditPwd2, 3)
self.mapper.addMapping(self.ui.comboBoxDept, 4, "text")
self.mapper.addMapping(self.ui.comboBoxUsage, 5)
self.mapper.addMapping(self.ui.dateEdit, 6)
self.mapper.addMapping(self.ui.plainTextEdit, 7)
self.mapper.toFirst()
if __name__ == '__main__':
app = QApplication(sys.argv)
vm = MemberVm()
widget = MemberV(vm)
widget2 = MemberV(vm)
widget.show()
widget2.show()
app.exec_()
pass
- MemberVm.py
from PySide.QtGui import QStandardItemModel, QStandardItem
class MemberVm(object):
'''
classdocs
'''
def __init__(self, params=None):
'''
Constructor
'''
self.model = QStandardItemModel()
_id = QStandardItem("")
name = QStandardItem("")
pwd = QStandardItem("")
pwd2 = QStandardItem("")
dept = QStandardItem("수")
usage = QStandardItem("o")
date = QStandardItem("2010-01-01")
etc = QStandardItem("비고")
self.model.setItem(0, 0, _id)
self.model.setItem(0, 1, name)
self.model.setItem(0, 2, pwd)
self.model.setItem(0, 3, pwd2)
self.model.setItem(0, 4, dept)
self.model.setItem(0, 5, usage)
self.model.setItem(0, 6, date)
self.model.setItem(0, 7, etc)
self.model.itemChanged.connect(self.printModel)
def printModel(self):
for col in range(7):
print(self.model.item(0,col).text())
- Ui_member.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Ui_member.ui'
#
# Created: Wed Oct 14 00:34:37 2015
# by: pyside-uic 0.2.15 running on PySide 1.2.2
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
from PySide.QtGui import QComboBox
from MyComboBox import MyComboBox
class Ui_member(object):
def setupUi(self, member):
member.setObjectName("member")
member.resize(212, 290)
self.gridLayout = QtGui.QGridLayout(member)
self.gridLayout.setObjectName("gridLayout")
self.label = QtGui.QLabel(member)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.lineEditId = QtGui.QLineEdit(member)
self.lineEditId.setObjectName("lineEditId")
self.gridLayout.addWidget(self.lineEditId, 0, 1, 1, 1)
self.label_2 = QtGui.QLabel(member)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.lineEditName = QtGui.QLineEdit(member)
self.lineEditName.setObjectName("lineEditName")
self.gridLayout.addWidget(self.lineEditName, 1, 1, 1, 1)
self.label_3 = QtGui.QLabel(member)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.lineEditPwd = QtGui.QLineEdit(member)
self.lineEditPwd.setObjectName("lineEditPwd")
self.gridLayout.addWidget(self.lineEditPwd, 2, 1, 1, 1)
self.label_4 = QtGui.QLabel(member)
self.label_4.setObjectName("label_4")
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1)
self.lineEditPwd2 = QtGui.QLineEdit(member)
self.lineEditPwd2.setObjectName("lineEditPwd2")
self.gridLayout.addWidget(self.lineEditPwd2, 3, 1, 1, 1)
self.label_5 = QtGui.QLabel(member)
self.label_5.setObjectName("label_5")
self.gridLayout.addWidget(self.label_5, 4, 0, 1, 1)
# self.comboBoxDept = QtGui.QComboBox(member)
self.comboBoxDept = MyComboBox(member)
self.comboBoxDept.setObjectName("comboBoxDept")
self.gridLayout.addWidget(self.comboBoxDept, 4, 1, 1, 1)
self.label_6 = QtGui.QLabel(member)
self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.comboBoxUsage = QtGui.QComboBox(member)
self.comboBoxUsage.setObjectName("comboBoxUsage")
self.gridLayout.addWidget(self.comboBoxUsage, 5, 1, 1, 1)
self.label_7 = QtGui.QLabel(member)
self.label_7.setObjectName("label_7")
self.gridLayout.addWidget(self.label_7, 6, 0, 1, 1)
self.dateEdit = QtGui.QDateEdit(member)
self.dateEdit.setObjectName("dateEdit")
self.gridLayout.addWidget(self.dateEdit, 6, 1, 1, 1)
self.label_8 = QtGui.QLabel(member)
self.label_8.setObjectName("label_8")
self.gridLayout.addWidget(self.label_8, 7, 0, 1, 1)
self.plainTextEdit = QtGui.QPlainTextEdit(member)
self.plainTextEdit.setObjectName("plainTextEdit")
self.gridLayout.addWidget(self.plainTextEdit, 7, 1, 1, 1)
self.retranslateUi(member)
QtCore.QMetaObject.connectSlotsByName(member)
def retranslateUi(self, member):
member.setWindowTitle(QtGui.QApplication.translate("member", "사용자", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("member", "아이디:", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("member", "이름:", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("member", "비번:", None, QtGui.QApplication.UnicodeUTF8))
self.label_4.setText(QtGui.QApplication.translate("member", "비번확인:", None, QtGui.QApplication.UnicodeUTF8))
self.label_5.setText(QtGui.QApplication.translate("member", "부서:", None, QtGui.QApplication.UnicodeUTF8))
self.label_6.setText(QtGui.QApplication.translate("member", "사용상태:", None, QtGui.QApplication.UnicodeUTF8))
self.label_7.setText(QtGui.QApplication.translate("member", "변경일:", None, QtGui.QApplication.UnicodeUTF8))
self.label_8.setText(QtGui.QApplication.translate("member", "비고:", None, QtGui.QApplication.UnicodeUTF8))
