16. 模型/视图编程¶
16.1 模型/视图架构¶
16.1.2 简单的例子¶
#!/usr/bin/env python
# encoding: utf-8
"""
@version :
@author :
@license :
@contact : ****@massclouds.com
@site : http://blog.csdn.net/***
@software: PyCharm
@time : 17-1-5 下午5:19
"""
from PyQt4.QtGui import QApplication,QTreeView,QFileSystemModel, QListView
from PyQt4.QtCore import QDir
import sys
if __name__ == '__main__':
app = QApplication(sys.argv)
# 1. 创建 模型 model */
model = QFileSystemModel() # 创建文件系统模型
model.setRootPath(QDir.currentPath()) # 指定要监视的目录
# 2. 创建 视图 view */
tree = QTreeView() # 创建树型视图
tree.setModel(model) # 为视图指定模型
tree.setRootIndex(model.index(QDir.currentPath() ))# 指定根索引
listw = QListView() # 创建列表视图
listw.setModel(model) # 为视图指定模型
listw.setRootIndex(model.index(QDir.currentPath()))# 指定根索引
tree.setWindowTitle("QTreeView")
tree.show()
listw.setWindowTitle("QListView")
listw.show()
app.exec_()
16.1.3 小试牛刀¶
1). QCompleter自动补全¶
#!/usr/bin/env python
#coding=utf-8
'''
FileName: main.py
'''
import sys
from PyQt4.QtCore import QString, SIGNAL,QStringList,Qt
from PyQt4.QtGui import QApplication, QLineEdit ,QCompleter,\
QDirModel, QStringListModel
# QCompleter补全文件路径
class FilePath(QLineEdit):
def __init__(self):
super(FilePath, self).__init__(None)
self.setWindowTitle("FilePath")
completer = QCompleter(self)
dir_model = QDirModel()
dir_model.setParent(self)
completer.setModel(dir_model)
self.setCompleter(completer)
# QCompleter补全单词
class CWord(QLineEdit):
def __init__(self):
super(CWord, self).__init__(None)
self.setWindowTitle("CWord")
word_list = QStringList()
word_list<<"Java"<<"C++"<<"C#"<<"PHP"<<"Perl"<<"Python"<<"Delphi"<<"Ruby"
completer2 = QCompleter(word_list, self)
completer2.setCaseSensitivity(Qt.CaseInsensitive)
self.setCompleter(completer2)
# QCompleter添加新单词
class AddNewWord(QLineEdit):
def __init__(self):
super(AddNewWord, self).__init__(None)
self.setWindowTitle("AddNewWord")
completer = QCompleter(self)
self.string_list_model = QStringListModel(self)
completer.setCaseSensitivity(Qt.CaseInsensitive)
completer.setModel(self.string_list_model)
self.setCompleter(completer)
self.connect(self, SIGNAL("editingFinished()"), self.editComplete)
self.word_list = QStringList()
def editComplete(self):
text = self.text()
if QString.compare(text, QString("")) != 0:
is_contains = self.word_list.contains(text, Qt.CaseInsensitive)
if not is_contains:
self.word_list<<text
self.string_list_model.setStringList(self.word_list)
if __name__ == "__main__":
app = QApplication(sys.argv)
# QCompleter补全文件路径
win_fpath = FilePath()
win_fpath.show()
# QCompleter补全单词
cword = CWord()
cword.show()
# QCompleter添加新单词
add_world = AddNewWord()
add_world.show()
app.exec_()
常用的方法
- void setMaxVisibleItems(int maxItems) 设置最大显示数目
- void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) 设置是否区分大小写
value – Qt::CaseInsensitive 0 (默认) 大小写不敏感 Qt::CaseSensitive 1 大小写敏感
void setModelSorting(ModelSorting sorting) 设置排序方式
QCompleter::ModelSorting取值如下:
value QCompleter::UnsortedModel 0 该模型是未排序 QCompleter::CaseSensitivelySortedModel 1 该模型是大小写敏感排序 QCompleter::CaseInsensitivelySortedModel 2 该模型是大小写不敏感排序的
3). 自动完成的QLineEdit(非使用QCompleter版)¶
#!/usr/bin/env python
# coding=utf-8
'''
FileName: main.py
'''
from PyQt4.QtGui import QLineEdit, QListView, QStringListModel, QFocusEvent
from PyQt4.QtCore import Qt, SIGNAL, SLOT, QStringList, QString, \
QPoint, QModelIndex, pyqtSlot
class CompleteLineEdit(QLineEdit):
def __init__(self, words):
super(CompleteLineEdit, self).__init__(None)
self.words = words # QStringList 整个完成列表的单词
self.listView = QListView(self)
self.model = QStringListModel(self)
self.listView.setWindowFlags(Qt.ToolTip)
self.connect(self, SIGNAL("textChanged(const QString &)"),
self, SLOT("setCompleter(const QString &)"))
self.connect(self.listView, SIGNAL("clicked(const QModelIndex &)"),
self, SLOT("completeText(const QModelIndex &)"))
def focusOutEvent(self, focus_event):
# self.listView.hide()
pass
@pyqtSlot("QKeyEvent")
def keyPressEvent(self, e):
if not self.listView.isHidden():
key = e.key()
count = self.listView.model().rowCount()
currentIndex = self.listView.currentIndex()
if Qt.Key_Down == key:
# 按向下方向键时,移动光标选中下一个完成列表中的项
row = currentIndex.row() + 1
if (row >= count):
row = 0
index = self.listView.model().index(row, 0)
self.listView.setCurrentIndex(index)
elif Qt.Key_Up == key:
# 按向下方向键时,移动光标选中上一个完成列表中的项
row = currentIndex.row() - 1
if (row < 0):
row = count - 1
index = self.listView.model().index(row, 0)
self.listView.setCurrentIndex(index)
elif Qt.Key_Escape == key:
# 按下Esc键时,隐藏完成列表
self.listView.hide()
elif Qt.Key_Enter == key or Qt.Key_Return == key:
# 按下回车键时,使用完成列表中选中的项,并隐藏完成列表
if (currentIndex.isValid()):
text = self.listView.currentIndex().data().toString()
self.setText(text)
self.listView.hide()
else:
# 其他情况,隐藏完成列表,并使用QLineEdit的键盘按下事件
self.listView.hide()
QLineEdit.keyPressEvent(self,e)
else:
QLineEdit.keyPressEvent(self,e)
# 动态的显示完成列表
@pyqtSlot("QString")
def setCompleter(self, text):
if (text.isEmpty()):
self.listView.hide()
return
if text.length() > 1 and not self.listView.isHidden():
return
# 如果完整的完成列表中的某个单词包含输入的文本,则加入要显示的完成列表串中
sl = QStringList()
for i in range(self.words.count()):
if self.words[i].contains(text):
sl << self.words[i]
self.model.setStringList(sl)
self.listView.setModel(self.model)
if (self.model.rowCount() == 0):
return
# Position the text edit
self.listView.setMinimumWidth(self.width())
self.listView.setMaximumWidth(self.width())
p = QPoint(0, self.height())
x = self.mapToGlobal(p).x()
y = self.mapToGlobal(p).y() + 1
self.listView.move(x, y)
self.listView.show()
# 点击完成列表中的项,使用此项自动完成输入的单词
@pyqtSlot("QModelIndex")
def completeText(self, index):
text = index.data().toString()
self.setText(text)
self.listView.hide()
#!/usr/bin/env python
#coding=utf-8
'''
FileName: main.py
'''
import sys
from PyQt4.QtCore import QStringList
from PyQt4.QtGui import QApplication, QWidget, QPushButton, QHBoxLayout
from completelineEdit import CompleteLineEdit
if __name__ == "__main__":
app = QApplication(sys.argv)
sl = QStringList() << "Biao" << "Bin" << "Huang" << "Hua" << "Hello" << "BinBin" << "Hallo"
widgetw = QWidget()
edit= CompleteLineEdit(sl)
button = QPushButton("Button")
layout = QHBoxLayout()
layout.addWidget(edit)
layout.addWidget(button)
widgetw.setLayout(layout)
widgetw.show()
# e = CompleteLineEdit(sl)
# e.show()
app.exec_()
16.2 模型类¶
16.2.1 基本概念¶
#!/usr/bin/env python
#coding=utf-8
#include <QApplication>
#include <QTreeView>
#include <QDebug>
#include <QStandardItemModel>
from PyQt4.QtCore import Qt, QModelIndex
from PyQt4.QtGui import QApplication, QStandardItemModel,QStandardItem, \
QPixmap, QIcon, QTreeView, QColor
import sys
if __name__ == "__main__":
app = QApplication(sys.argv)
view = QTreeView()
# 1. 模型
'''
PyQt使用Model时,如果Model创建时未设置parent,则运行完退出时会报错:
QObject::startTimer: QTimer can only be used with threads started with QThread
'''
# model = QStandardItemModel() # 创建标准项模型
model = QStandardItemModel(view) # 创建标准项模型
# 获取模型的根项(Root Item),根项是不可见的
parentItem = model.invisibleRootItem()
# 创建标准项item0,并设置显示文本,图标和工具提示
item0 = QStandardItem()
item0.setText("A")
pixmap0 = QPixmap(50,50)
pixmap0.fill(QColor("red"))
# pixmap0.fill(Qt.red)
item0.setIcon(QIcon(pixmap0))
item0.setToolTip("indexA")
parentItem.appendRow(item0) # 将item0 作为根项的子项
# 将创建的标准项作为新的父项
parentItem = item0
# 创建新的标准项,它将作为item0的子项
item1 = QStandardItem()
item1.setText("B")
pixmap1 = QPixmap(50,50)
pixmap1.fill(Qt.blue)
item1.setIcon(QIcon(pixmap1))
item1.setToolTip("indexB")
parentItem.appendRow(item1)
# 创建新的标准项,这里使用了另一种方法来设置文本、图标和工具提示
item2 = QStandardItem()
pixmap2 = QPixmap(50,50)
pixmap2.fill(Qt.green)
item2.setData("C", Qt.EditRole) # 等同于 setText("C")
item2.setData("indexC", Qt.ToolTipRole) # 等同于 setToolTip("indexB")
item2.setData(QIcon(pixmap2), Qt.DecorationRole) #等同于 setIcon(QIcon(pixmap1))
parentItem.appendRow(item2)
# 在树视图中显示模型
view.setModel(model)
view.show()
# 获取item0的索引并输出item0的子项数目,然后输出了item1的显示文本和工具提示
indexA = model.index(0, 0, QModelIndex())
print "indexA row count: " , model.rowCount(indexA)
indexB = model.index(0, 0, indexA)
print "indexB text: " , model.data(indexB, Qt.EditRole).toString()
print "indexB toolTip: " , model.data(indexB, Qt.ToolTipRole).toString()
app.exec_()
16.2.2 创建新的模型¶
1.¶
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtCore import QAbstractListModel, QStringList, QModelIndex, QVariant, Qt, QString
class StringListModel(QAbstractListModel):
def __init__(self,stringList,parent = None):
super(StringListModel, self).__init__(parent)
self.stringList = QStringList(stringList)
# int rowCount(const QModelIndex &parent = QModelIndex()) const;
# QVariant data(const QModelIndex &index, int role) const;
# QVariant headerData(int section, Qt::Orientation orientation,
# int role = Qt::DisplayRole) const;
def rowCount(self,parent=QModelIndex()):
return self.stringList.count()
def data(self,index,role= Qt.DisplayRole):
if (not index.isValid()):
return QVariant()
if (index.row() >= self.stringList.count):
return QVariant()
if (role == Qt.DisplayRole):
return self.stringList[index.row()]
else:
return QVariant()
def headerData(self,section, orientation, role= Qt.DisplayRole):
if (role != Qt.DisplayRole):
return QVariant()
if (orientation == Qt.Horizontal):
return QString("Column %1").arg(section)
else:
return QString("Row %1").arg(section)
#!/usr/bin/env python
#coding=utf-8
#include <QApplication>
#include <QListView>
#include <QTableView>
#include <QDebug>
import sys
from PyQt4.QtCore import QStringList
from PyQt4.QtGui import QApplication, QListView, QTableView
from stringlistmodel import StringListModel
if __name__ == "__main__":
app = QApplication(sys.argv)
qlist = QStringList()
qlist.append("a")
qlist.append("b")
qlist.append("c")
qlist.append("abcd")
model = StringListModel(qlist)
qlistView = QListView()
qlistView.setModel(model)
qlistView.show()
tableView = QTableView()
tableView.setModel(model)
tableView.show()
app.exec_()
2.¶
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtCore import QAbstractListModel, QStringList, QModelIndex, QVariant, Qt, QString, QAbstractItemModel, SIGNAL
class StringListModel(QAbstractListModel):
def __init__(self,stringList,parent = None):
super(StringListModel, self).__init__(parent)
self.stringList = QStringList(stringList)
# int rowCount(const QModelIndex &parent = QModelIndex()) const;
# QVariant data(const QModelIndex &index, int role) const;
# QVariant headerData(int section, Qt::Orientation orientation,
# int role = Qt::DisplayRole) const;
# 编辑功能用到的两个函数
# Qt::ItemFlags flags(const QModelIndex &index) const;
# bool setData(const QModelIndex &index, const QVariant &value,
# int role = Qt::EditRole);
def rowCount(self, parent=None, *args, **kwargs):
return self.stringList.count()
def data(self,index,role= Qt.DisplayRole):
if (not index.isValid()):
return QVariant()
if (index.row() >= self.stringList.count):
return QVariant()
if (role == Qt.DisplayRole or role == Qt.EditRole):
return self.stringList[index.row()]
else:
return QVariant()
def headerData(self,section, orientation, role= Qt.DisplayRole):
if (role != Qt.DisplayRole):
return QVariant()
if (orientation == Qt.Horizontal):
return QString("Column %1").arg(section)
else:
return QString("Row %1").arg(section)
# 以下是实现编辑功能添加的两个函数
def flags(self,index):
if (not index.isValid()):
return Qt.ItemIsEnabled
return super(StringListModel, self).flags(index) | Qt.ItemIsEditable
def setData(self, index, value, role= Qt.DisplayRole):
if (index.isValid() and role == Qt.EditRole):
self.stringList.replace(index.row(), value.toString())
self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),index, index)
return True
return False
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtCore import QStringList
from PyQt4.QtGui import QApplication, QListView, QTableView
import sys
from stringlistmodel import StringListModel
if __name__ == "__main__":
app = QApplication(sys.argv)
qlist = QStringList()
qlist.append("a")
qlist.append("b")
qlist.append("c")
listView = QListView()
tableView = QTableView()
'''
PyQt使用Model时,如果Model创建时未设置parent,则运行完退出时会报错:
QObject::startTimer: QTimer can only be used with threads started with QThread
'''
# model = StringListModel(qlist)
model = StringListModel(qlist,listView)
listView.setModel(model)
listView.show()
tableView.setModel(model)
tableView.show()
app.exec_()
3.¶
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtCore import QAbstractListModel, QStringList, QModelIndex, QVariant, Qt, QString, QAbstractItemModel, SIGNAL
class StringListModel(QAbstractListModel):
def __init__(self,stringList,parent = None):
super(StringListModel, self).__init__(parent)
self.stringList = QStringList(stringList)
# int rowCount(const QModelIndex &parent = QModelIndex()) const;
# QVariant data(const QModelIndex &index, int role) const;
# QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
# // 编辑功能用到的两个函数
# Qt::ItemFlags flags(const QModelIndex &index) const;
# bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
#
# // 插入和删除行用到的两个函数
# bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
# bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
def rowCount(self,parent= QModelIndex()):
return self.stringList.count()
def data(self,index,role= Qt.DisplayRole):
if (not index.isValid()):
return QVariant()
if (index.row() >= self.stringList.count):
return QVariant()
if (role == Qt.DisplayRole):
return self.stringList[index.row()]
else:
return QVariant()
def headerData(self,section, orientation, role= Qt.DisplayRole):
if (role != Qt.DisplayRole):
return QVariant()
if (orientation == Qt.Horizontal):
return QString("Column %1").arg(section)
else:
return QString("Row %1").arg(section)
# 以下是实现编辑功能添加的两个函数
def flags(self,index):
if (not index.isValid()):
return Qt.ItemIsEnabled
return super(StringListModel, self).flags(index) | Qt.ItemIsEditable
def setData(self, index, value, role= Qt.DisplayRole):
if (index.isValid() and role == Qt.EditRole):
self.stringList.replace(index.row(), value.toString())
self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),index, index)
return True
return False
# 以下是插入和删除行用到的两个函数
def insertRows(self,position, rows, parent = QModelIndex()):
self.beginInsertRows(QModelIndex(), position, position+rows-1)
for i in range(rows):
self.stringList.insert(position, "")
self.endInsertRows()
return True
def removeRows(self,position, rows, parent = QModelIndex()):
self.beginRemoveRows(QModelIndex(), position, position+rows-1)
for i in range(rows):
self.stringList.removeAt(position)
self.endRemoveRows()
return True
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtCore import QStringList
from PyQt4.QtGui import QApplication, QListView, QTableView
import sys
from stringlistmodel import StringListModel
if __name__ == "__main__":
app = QApplication(sys.argv)
qlist = QStringList()
qlist.append("a")
qlist.append("b")
qlist.append("c")
listView = QListView()
tableView = QTableView()
'''
PyQt使用Model时,如果Model创建时未设置parent,则运行完退出时会报错:
QObject::startTimer: QTimer can only be used with threads started with QThread
'''
# model = StringListModel(qlist)
model = StringListModel(qlist,listView)
listView.setModel(model)
listView.show()
tableView.setModel(model)
tableView.show()
# 插入删除行
model.insertRows(3, 2)
model.removeRows(0, 1)
app.exec_()
16.3 视图类¶
16.3.1 基本概念¶
16.3.2 处理项目选择¶
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtCore import QString, QModelIndex
from PyQt4.QtGui import QTableView, QMainWindow, \
QStandardItemModel, QStandardItem, QItemSelection, \
QItemSelectionModel
from PyQt4 import uic
class MainWindow(QMainWindow):
def __init__(self,parent=None):
super(MainWindow, self).__init__(None)
uic.loadUi("mainwindow.ui",self)
model = QStandardItemModel(7, 4, self)
for row in range(7):
for column in range(4):
item = QStandardItem(QString("%1").arg(row * 4 + column))
model.setItem(row, column, item)
tableView = QTableView()
tableView.setModel(model)
self.setCentralWidget(tableView)
#获取视图的项目选择模型
selectionModel = tableView.selectionModel()
# 定义左上角和右下角的索引,然后使用这两个索引创建选择
topLeft = model.index(1, 1, QModelIndex())
bottomRight = model.index(5, 2, QModelIndex())
selection = QItemSelection(topLeft, bottomRight)
# 使用指定的选择模式来选择项目
selectionModel.select(selection, QItemSelectionModel.Select)
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtGui import QApplication
import sys
from mainwindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
QTiemSelectionModel::Toggle
#!/usr/bin/env python
# coding=utf-8
from PyQt4.QtCore import QString, QModelIndex
from PyQt4.QtGui import QTableView, QMainWindow, \
QStandardItemModel, QStandardItem, QItemSelection, \
QItemSelectionModel
from PyQt4 import uic
try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
uic.loadUi("mainwindow.ui", self)
model = QStandardItemModel(7, 4, self)
for row in range(7):
for column in range(4):
item = QStandardItem(QString("%1").arg(row * 4 + column))
model.setItem(row, column, item)
self.tableView = QTableView()
self.tableView.setModel(model)
self.setCentralWidget(self.tableView)
# 获取视图的项目选择模型
selectionModel = self.tableView.selectionModel()
# 定义左上角和右下角的索引,然后使用这两个索引创建选择
topLeft = model.index(1, 1, QModelIndex())
bottomRight = model.index(5, 2, QModelIndex())
selection = QItemSelection(topLeft, bottomRight)
# 使用指定的选择模式来选择项目
selectionModel.select(selection, QItemSelectionModel.Select)
self.mainToolBar.addAction(_fromUtf8("当前项目"), self.getCurrentItemData)
self.mainToolBar.addAction(_fromUtf8("切换选择"), self.toggleSelection)
# 输出当前项目的内容
def getCurrentItemData(self, ):
print "当前项目的内容:", \
self.tableView.selectionModel().currentIndex().data().toString()
# 切换选择的项目
def toggleSelection(self):
topLeft = self.tableView.model().index(0, 0, QModelIndex())
bottomRight = self.tableView.model().index(
self.tableView.model().rowCount(QModelIndex()) - 1,
self.tableView.model().columnCount(QModelIndex()) - 1, QModelIndex())
curSelection = QItemSelection(topLeft, bottomRight)
self.tableView.selectionModel().select(curSelection, QItemSelectionModel.Toggle)
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtGui import QApplication
import sys
from mainwindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
#!/usr/bin/env python
# coding=utf-8
from PyQt4.QtCore import QString, QModelIndex, SIGNAL
from PyQt4.QtGui import QTableView, QMainWindow, \
QStandardItemModel, QStandardItem, QItemSelection, \
QItemSelectionModel
from PyQt4 import uic
try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
uic.loadUi("mainwindow.ui", self)
model = QStandardItemModel(7, 4, self)
for row in range(7):
for column in range(4):
item = QStandardItem(QString("%1").arg(row * 4 + column))
model.setItem(row, column, item)
self.tableView = QTableView()
self.tableView.setModel(model)
self.setCentralWidget(self.tableView)
# 获取视图的项目选择模型
selectionModel = self.tableView.selectionModel()
# 定义左上角和右下角的索引,然后使用这两个索引创建选择
topLeft = model.index(1, 1, QModelIndex())
bottomRight = model.index(5, 2, QModelIndex())
selection = QItemSelection(topLeft, bottomRight)
# 使用指定的选择模式来选择项目
selectionModel.select(selection, QItemSelectionModel.Select)
self.mainToolBar.addAction(_fromUtf8("当前项目"), self.getCurrentItemData)
self.mainToolBar.addAction(_fromUtf8("切换选择"), self.toggleSelection)
self.connect(selectionModel,SIGNAL("selectionChanged(QItemSelection,QItemSelection)"),
self.updateSelection)
self.connect(selectionModel, SIGNAL("currentChanged(QModelIndex,QModelIndex)"),
self.changeCurrent)
# 多个视图共享选择
self.tableView2 = QTableView()
self.tableView2.setWindowTitle("tableView2")
self.tableView2.resize(400, 300)
self.tableView2.setModel(model)
self.tableView2.setSelectionModel(selectionModel)
self.tableView2.show()
# 输出当前项目的内容
def getCurrentItemData(self, ):
print "当前项目的内容:", \
self.tableView.selectionModel().currentIndex().data().toString()
# 切换选择的项目
def toggleSelection(self):
topLeft = self.tableView.model().index(0, 0, QModelIndex())
bottomRight = self.tableView.model().index(
self.tableView.model().rowCount(QModelIndex()) - 1,
self.tableView.model().columnCount(QModelIndex()) - 1, QModelIndex())
curSelection = QItemSelection(topLeft, bottomRight)
self.tableView.selectionModel().select(curSelection, QItemSelectionModel.Toggle)
# 更新选择
def updateSelection(self,selected, deselected):
mlist = selected.indexes()
# 为现在选择的项目填充值
for index in mlist:
text = QString("(%1,%2)").arg(index.row()).arg(index.column())
self.tableView.model().setData(index, text)
mlist = deselected.indexes()
# 清空上一次选择的项目的内容
for index in mlist:
self.tableView.model().setData(index, "")
# 改变当前项目
def changeCurrent(self, current, previous):
print QString("move(%1,%2) to (%3,%4)")\
.arg(previous.row()).arg(previous.column()) \
.arg(current.row()).arg(current.column())
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtGui import QApplication
import sys
from mainwindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
16.4 委托类¶
16.4.1 基本概念¶
16.4.2 自定义委托¶
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtCore import QString, QModelIndex, SIGNAL
from PyQt4.QtGui import QTableView, QMainWindow, \
QStandardItemModel, QStandardItem, QItemSelection, \
QItemSelectionModel
from PyQt4 import uic
from spinboxdelegate import SpinBoxDelegate
try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
uic.loadUi("mainwindow.ui", self)
model = QStandardItemModel(7, 4, self)
for row in range(7):
for column in range(4):
item = QStandardItem(QString("%1").arg(row * 4 + column))
model.setItem(row, column, item)
self.tableView = QTableView()
self.tableView.setModel(model)
self.setCentralWidget(self.tableView)
# 获取视图的项目选择模型
selectionModel = self.tableView.selectionModel()
# 定义左上角和右下角的索引,然后使用这两个索引创建选择
topLeft = model.index(1, 1, QModelIndex())
bottomRight = model.index(5, 2, QModelIndex())
selection = QItemSelection(topLeft, bottomRight)
# 使用指定的选择模式来选择项目
selectionModel.select(selection, QItemSelectionModel.Select)
self.mainToolBar.addAction(_fromUtf8("当前项目"), self.getCurrentItemData)
self.mainToolBar.addAction(_fromUtf8("切换选择"), self.toggleSelection)
self.connect(selectionModel,SIGNAL("selectionChanged(QItemSelection,QItemSelection)"),
self.updateSelection)
self.connect(selectionModel, SIGNAL("currentChanged(QModelIndex,QModelIndex)"),
self.changeCurrent)
# 多个视图共享选择
self.tableView2 = QTableView()
self.tableView2.setWindowTitle("tableView2")
self.tableView2.resize(400, 300)
self.tableView2.setModel(model)
self.tableView2.setSelectionModel(selectionModel)
self.tableView2.show()
# 使用自定义委托
delegate = SpinBoxDelegate(self)
self.tableView.setItemDelegate(delegate)
# 输出当前项目的内容
def getCurrentItemData(self, ):
print "当前项目的内容:", \
self.tableView.selectionModel().currentIndex().data().toString()
# 切换选择的项目
def toggleSelection(self):
topLeft = self.tableView.model().index(0, 0, QModelIndex())
bottomRight = self.tableView.model().index(
self.tableView.model().rowCount(QModelIndex()) - 1,
self.tableView.model().columnCount(QModelIndex()) - 1, QModelIndex())
curSelection = QItemSelection(topLeft, bottomRight)
self.tableView.selectionModel().select(curSelection, QItemSelectionModel.Toggle)
# 更新选择
def updateSelection(self,selected, deselected):
mlist = selected.indexes()
# 为现在选择的项目填充值
for index in mlist:
text = QString("(%1,%2)").arg(index.row()).arg(index.column())
self.tableView.model().setData(index, text)
mlist = deselected.indexes()
# 清空上一次选择的项目的内容
for index in mlist:
self.tableView.model().setData(index, "")
# 改变当前项目
def changeCurrent(self, current, previous):
print QString("move(%1,%2) to (%3,%4)")\
.arg(previous.row()).arg(previous.column()) \
.arg(current.row()).arg(current.column())
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtGui import QItemDelegate, QSpinBox
from PyQt4.QtCore import Qt
class SpinBoxDelegate(QItemDelegate):
def __init__(self,parent=None):
super(SpinBoxDelegate, self).__init__(parent)
# QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
# const QModelIndex &index) const;
#
# void setEditorData(QWidget *editor, const QModelIndex &index) const;
# void setModelData(QWidget *editor, QAbstractItemModel *model,
# const QModelIndex &index) const;
#
# void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,
# const QModelIndex &index) const;
# 创建编辑器 */
def createEditor(self,parent, option, index ):
editor = QSpinBox(parent)
editor.setMinimum(0)
editor.setMaximum(100)
return editor
# 为编辑器设置数据 */
def setEditorData(self,editor, index):
value,flag = index.model().data(index, Qt.EditRole).toInt()
spinBox = editor
spinBox.setValue(value)
# 将数据写入到模型 */
def setModelData(self, editor, model, index):
spinBox = editor
spinBox.interpretText()
value = spinBox.value()
model.setData(index, value, Qt.EditRole)
# 更新编辑器几何布局 */
def updateEditorGeometry(self,editor, option, index ):
editor.setGeometry(option.rect)
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtGui import QApplication
import sys
from mainwindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
16.6 在项目视图中启用拖放¶
16.6.1 在便捷类中启用拖放¶
#!/usr/bin/env python
# coding=utf-8
from PyQt4.QtGui import QListWidgetItem, QApplication, \
QIcon, QListWidget, QTreeWidget,QTreeWidgetItem, QTableWidget,QTableWidgetItem, QAbstractItemView
from PyQt4.QtCore import Qt, QStringList
import sys
if __name__ == "__main__":
app = QApplication(sys.argv)
# #********************* 1. QListWidget ******************/
listWidget = QListWidget()
# 一种添加项目的简便方法
QListWidgetItem("a", listWidget)
# 添加项目的另一种方法,这样还可以进行各种设置
listWidgetItem = QListWidgetItem()
listWidgetItem.setText("b")
listWidgetItem.setIcon(QIcon("./yafeilinux.png"))
listWidgetItem.setToolTip("this is b!")
listWidget.insertItem(1, listWidgetItem)
# 设置排序为倒序
listWidget.sortItems(Qt.DescendingOrder)
# 显示列表部件
listWidget.show()
#********************** 2. QTreeWidget *******************/
treeWidget = QTreeWidget()
# 必须设置列数
treeWidget.setColumnCount(2)
# 设置标头
headers = QStringList()
headers.append("name")
headers.append("year")
treeWidget.setHeaderLabels(headers)
# 添加项目
grade1 = QTreeWidgetItem(treeWidget)
grade1.setText(0,"Grade1")
student = QTreeWidgetItem(grade1)
student.setText(0,"Tom")
student.setText(1,"1986")
grade2 = QTreeWidgetItem(treeWidget, grade1)
grade2.setText(0,"Grade2")
treeWidget.show()
#********************* 3. QTableWidget ********************/
# 创建表格部件,同时指定行数和列数
tableWidget = QTableWidget(3, 2)
# 创建表格项目,并插入到指定单元
tableWidgetItem = QTableWidgetItem("qt")
tableWidget.setItem(1, 1, tableWidgetItem)
# 创建表格项目,并将它们作为标头
headerV = QTableWidgetItem("first")
tableWidget.setVerticalHeaderItem(0,headerV)
headerH = QTableWidgetItem("ID")
tableWidget.setHorizontalHeaderItem(0,headerH)
tableWidget.show()
#/************ 4. 为listWidget启用拖放 *************/
# 设置选择模式为单选
listWidget.setSelectionMode(QAbstractItemView.SingleSelection)
# 启用拖动
listWidget.setDragEnabled(True)
# 设置接受拖放
listWidget.viewport().setAcceptDrops(True)
# 设置显示将要被放置的位置
listWidget.setDropIndicatorShown(True)
# 设置拖放模式为移动项目,如果不设置,默认为复制项目
listWidget.setDragDropMode(QAbstractItemView.InternalMove)
app.exec_()
16.6.2 在模型/视图类中启用拖放¶
#!/usr/bin/env python
# coding=utf-8
from PyQt4.QtGui import QApplication, QAbstractItemView, QListView,QTableView
from PyQt4.QtCore import QStringList
import sys
from stringlistmodel import StringListModel
if __name__ == "__main__":
app = QApplication(sys.argv)
slist = QStringList()
slist.append("a")
slist.append("b")
slist.append("c")
slist.append("d")
listView = QListView()
'''
PyQt使用Model时,如果Model创建时未设置parent,则运行完退出时会报错:
QObject::startTimer: QTimer can only be used with threads started with QThread
'''
# model = StringListModel(slist)
model = StringListModel(slist,listView)
listView.setModel(model)
listView.show()
tableView = QTableView ()
tableView.setModel(model)
tableView.show()
# 插入删除行
model.insertRows(3, 2)
model.removeRows(0, 1)
# 启用拖放功能
listView.setSelectionMode(QAbstractItemView.ExtendedSelection) # 设置拖放为移动, 默认为复制
listView.setDragEnabled(True) # 启用拖动
listView.setAcceptDrops(True) # 设置接受拖放
listView.setDropIndicatorShown(True) # 设置显示将要被放置的位置
app.exec_()
16.7 其他内容¶
16.7.1 代理模型¶
#!/usr/bin/env python
# coding=utf-8
from PyQt4.QtCore import QString, QStringList, QRegExp
from PyQt4.QtGui import QMainWindow, QStringListModel, QSortFilterProxyModel
from PyQt4 import uic
try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
class MainWindow (QMainWindow):
def __init__(self,parent = None):
super(MainWindow, self).__init__(parent)
uic.loadUi("mainwindow.ui", self)
strlist = QStringList()
strlist.append("yafei")
strlist.append("yafeilinux")
strlist.append("Qt")
strlist.append("Qt Creator")
listModel = QStringListModel(strlist, self)
self.filterModel = QSortFilterProxyModel(self)
# 为代理模型添加源模型
self.filterModel.setSourceModel(listModel)
# 在视图中使用代理模型
self.listView.setModel(self.filterModel)
def on_pushButton_clicked(self):
rx = QRegExp(self.lineEdit.text())
self.filterModel.setFilterRegExp(rx)
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtGui import QApplication
import sys
from mainwindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
16.7.2 数据-窗口映射器¶
#!/usr/bin/env python
# coding=utf-8
from PyQt4.QtCore import QString
from PyQt4.QtGui import QMainWindow, QStandardItemModel, QStandardItem, \
QDataWidgetMapper, QTableView
from PyQt4 import uic
try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
class MainWindow (QMainWindow):
def __init__(self,parent = None):
super(MainWindow, self).__init__(parent)
uic.loadUi("mainwindow.ui", self)
model = QStandardItemModel(3, 2, self)
model.setItem(0, 0, QStandardItem(_fromUtf8("xiaoming")))
model.setItem(0, 1, QStandardItem(_fromUtf8("0")))
model.setItem(1, 0, QStandardItem(_fromUtf8("xiaogang")))
model.setItem(1, 1, QStandardItem(_fromUtf8("5")))
model.setItem(2, 0, QStandardItem(_fromUtf8("xiaohong")))
model.setItem(2, 1, QStandardItem(_fromUtf8("0")))
model.setItem(3, 0, QStandardItem(_fromUtf8("赵六")))
model.setItem(3, 1, QStandardItem(_fromUtf8("8")))
self.mapper = QDataWidgetMapper(self)
# 设置模型
self.mapper.setModel(model)
# 设置窗口部件和模型中的列的映射
self.mapper.addMapping(self.lineEdit, 0)
self.mapper.addMapping(self.lineEdit_2, 1)
# 显示模型中的第一行
self.mapper.toFirst()
#----------------------------------------------------------
tableview = QTableView()
tableview.setModel(model)
tableview.show()
# 上一条按钮
def on_pushButton_clicked(self):
self.mapper.toPrevious()
# 下一条按钮
def on_pushButton_2_clicked(self):
self.mapper.toNext()
#!/usr/bin/env python
#coding=utf-8
from PyQt4.QtGui import QApplication
import sys
from mainwindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()