MVC
mvc不仅仅是qt里面的概念,(Model View Controler)的简称
Model是一个数据模型、一个虚拟的东西,显示不出来的,如果我们要把这些数据显示出来,就需要使用view
view:用来显示Model这种数据
controler:如果我们要编辑数据,就需要使用controler
不使用controler,我们只能对数据进行查看不能编辑
就像我们去火车站买票,可以看到火车站有一个大屏幕,显示现在的票量,它后台的数据库就可以当作一个Model,一个数据模型,大显示器就像一个View,它可以显示后台的数据,现在有多少票,还剩下多少票,而且是实时动态刷新的,柜台里的电脑也可以是一个view,可以多个view显示同一个model,也就是说同一个数据模型,可以在不同的view上显示。那么在某一个view上面编辑了model数据,那么所有的view都会刷新这个数据
在pyqt中,view包括List View、Tree View、Table View、Column View
首先我们创建含有两个List View的UI布局:
List Widget:含有一些常用的功能,可以在属性编辑中处理元素
List View:没有属性设置,仅提供了view窗口,需要加上数据模型,通过分开控制,可以实现高度自定义
接下来就用List View来实现List Widget的功能
两个List View是没有任何区别的,两个List View使用同一个数据模型
Designer.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mvc.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(625, 385)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(32, 24, 525, 218))
self.widget.setObjectName("widget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.listView1 = QtWidgets.QListView(self.widget)
self.listView1.setObjectName("listView1")
self.verticalLayout.addWidget(self.listView1)
self.horizontalLayout.addLayout(self.verticalLayout)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.label_2 = QtWidgets.QLabel(self.widget)
self.label_2.setObjectName("label_2")
self.verticalLayout_2.addWidget(self.label_2)
self.listView_2 = QtWidgets.QListView(self.widget)
self.listView_2.setObjectName("listView_2")
self.verticalLayout_2.addWidget(self.listView_2)
self.horizontalLayout.addLayout(self.verticalLayout_2)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 625, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "List View"))
self.label_2.setText(_translate("MainWindow", "List Widget"))
view.py
# coding=utf-8
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from b.MVC.mvc import Ui_MainWindow
from b.MVC.mvc_core import ListMode
class DemonWindow(Ui_MainWindow, QtWidgets.QMainWindow):
"""
创建list model
"""
def __init__(self, parent=None):
super(Ui_MainWindow, self).__init__(parent)
self.setupUi(self)
self.list_model = ListMode(self.listView1)
self.listView1.setModel(self.list_model)
self.listView_2.setModel(self.list_model)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv) # sys.argv是一组命令行参数的列表,该程序会被cou进行轮询
ex = DemonWindow()
ex.show()
app.exec_()
4,从Model中创建一个Model
self.list_model = ListMode(self.listView1)
仅创建一个Model,Model和View还没有产生关系,在我们实际编写过程中,我们的数据模型一定要写程实例的属性,这个实例我们要放在self下面,否则,在其他的方法里要操作这个模型的话,就访问不到了
5.将List View1的模型设置为上面实例化的self.list_model
self.listView1.setModel(self.list_model)
Model.py:
# coding=utf-8
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
class ListMode(QtCore.QAbstractListModel):
"""
创建list model
"""
def __init__(self, parent=None):
super(ListMode, self).__init__(parent)
self.list_data = list("ABCDE")
def rowCount(self, parent=QtCore.QModelIndex()):
"""
:param self:
:param parent:
:param args:
:param kwargs:
:return:
"""
return len(self.list_data)
def data(self, index = QtCore.QModelIndex(), role=QtCore.Qt.DisplayRole):
"""
:param QModelIndex:
:param role:
:return:
"""
if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
return self.list_data[index.row()]
# 设置前景色
if role == QtCore.Qt.ForegroundRole:
return QtGui.QColor(255, 0, 0)
# 设置背景色
if role == QtCore.Qt.BackgroundColorRole:
return QtGui.QColor(0, 255, 0)
def flags(self, index=QtCore.QModelIndex()):
"""
:param index:
:return:
"""
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
def setData(self, index = QtCore.QModelIndex(), value=None, role=QtCore.Qt.EditRole):
"""
:param QModelIndex:
:param value:
:param role:
:return:
"""
if value != None:
self.list_data[index.row()] = value
self.dataChanged.emit(index, index)
return True
1.QtCore.QAbstractListModel继承自QtCore.QAbstractItemModel,与之对应的还有QtCore.QAbstractTableModel针对List View使用QtCore.QAbstractListModel就可以了,使用QtCore.QAbstractItemModel也可以,但是我们要写更多的方法
创建完一个QtCore.QAbstractListModel,本身是不知道谁要用它,所以没有一个基本的数据,直接用QtCore.QAbstractListModel是用不了的,所以我们要继承他,来写一个自己的模型
2.导入QT.Core
from PyQt5 import QtCore
我们的数据模型实际上一个不能显示的东西,是一个虚拟的东西,只能在后台有一层数据,但是显示不出来,在QT中,能显示的都是QWidgets,像图标之类的都是GUI,纯数据类型的就是Qt.Core里边的。
3.创建一个LIst Model继承自QtCore.QAbstractListModel
初始化函数,创建一个单纯的Model
# coding=utf-8
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
class ListMode(QtCore.QAbstractListModel):
"""
创建list model
"""
def __init__(self, parent=None):
super(ListMode, self).__init__(parent)
6.添加rowCount(self, parent=QtCore.QModelIndex()),并设置返回值5
def rowCount(self, parent=QtCore.QModelIndex()):
"""
:param self:
:param parent:
:param args:
:param kwargs:
:return:
"""
return 5
我们设置了行数,但是每行里要显示的数据还没有,接下来我们定义数据
7.添加data(self, index = QtCore.QModelIndex(), role=QtCore.Qt.DisplayRole),role为一种显示状态
def data(self, index = QtCore.QModelIndex(), role=QtCore.Qt.DisplayRole):
"""
:param QModelIndex:
:param role:
:return:
"""
if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
return 0
8.添加flags(self, index=QtCore.QModelIndex()),状态激活,是否可以选择、是否可以拖拽
def flags(self, index=QtCore.QModelIndex()):
"""
:param index:
:return:
"""
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
在model中, index是经常用到的,涉及到行列及上下关系,他并不是一个整数
9.设置setdata,数据修改,
def setData(self, index = QtCore.QModelIndex(), value=None, role=QtCore.Qt.EditRole):
"""
:param QModelIndex:
:param value:
:param role:
:return:
"""
if value != None:
self.list_data[index.row()] = value
self.dataChanged.emit(index, index)
return True
我们在修改数据时,都是在编辑状态下。