Skip to content

Instantly share code, notes, and snippets.

@345161974
Created February 28, 2017 08:31
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save 345161974/dd5003ed9b706adc557ee12e6a344c6e to your computer and use it in GitHub Desktop.
Save 345161974/dd5003ed9b706adc557ee12e6a344c6e to your computer and use it in GitHub Desktop.
PyQt QTableView with CheckBox and Model Update demo code(PyQt 4.8.7, Python 3.4.3)
''' pqt_tableview3.py
explore PyQT's QTableView Model
using QAbstractTableModel to present tabular data
allow table sorting by clicking on the header title
used the Anaconda package (comes with PyQt4) on OS X
(dns)
'''
#coding=utf-8
import operator # used for sorting
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtGui, QtCore
from time import time
import threading
class MyWindow(QWidget):
def __init__(self, dataList, header, *args):
QWidget.__init__(self, *args)
# setGeometry(x_pos, y_pos, width, height)
self.setGeometry(70, 150, 1326, 582)
self.setWindowTitle("Click on the header to sort table")
self.table_model = MyTableModel(self, dataList, header)
self.table_view = QTableView()
#self.table_view.setSelectionMode(QAbstractItemView.SingleSelection)
self.table_view.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.table_view.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
# bind cell click to a method reference
self.table_view.clicked.connect(self.showSelection)
self.table_view.clicked.connect(self.selectRow)
self.table_view.setModel(self.table_model)
# enable sorting
self.table_view.setSortingEnabled(True)
layout = QVBoxLayout(self)
layout.addWidget(self.table_view)
self.setLayout(layout)
def update_model(self, datalist, header):
self.table_model2 = MyTableModel(self, dataList, header)
self.table_view.setModel(self.table_model2)
self.table_view.update()
def showSelection(self, item):
cellContent = item.data()
# print(cellContent) # test
sf = "You clicked on {}".format(cellContent)
# display in title bar for convenience
self.setWindowTitle(sf)
def selectRow(self, index):
# print("current row is %d", index.row())
pass
class MyTableModel(QAbstractTableModel):
"""
keep the method names
they are an integral part of the model
"""
def __init__(self, parent, mylist, header, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.mylist = mylist
self.header = header
self.timer = QtCore.QTimer()
self.change_flag = True
self.timer.timeout.connect(self.updateModel)
self.timer.start(1000)
# self.rowCheckStateMap = {}
def setDataList(self, mylist):
self.mylist = mylist
self.layoutAboutToBeChanged.emit()
self.dataChanged.emit(self.createIndex(0, 0), self.createIndex(self.rowCount(0), self.columnCount(0)))
self.layoutChanged.emit()
def updateModel(self):
dataList2 = []
if self.change_flag is True:
dataList2 = [
[QtGui.QCheckBox("关"), 0, '063802', '01', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '063802', '02', 'cu1705,cu1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '063802', '03', 'zn1705,zn1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '063802', '04', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '063802', '01', 'zn1705,zn1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '063802', '02', 'ru1705,ru1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '063802', '02', 'ni1705,ni1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '063802', '01', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
]
self.change_flag = False
elif self.change_flag is False:
dataList2 = [
[QtGui.QCheckBox("关"), 0, '058176', '01', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '02', 'cu1705,cu1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '03', 'zn1705,zn1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '04', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '01', 'zn1705,zn1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '02', 'ru1705,ru1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '02', 'ni1705,ni1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '01', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
]
self.change_flag = True
self.mylist = dataList2
self.layoutAboutToBeChanged.emit()
self.dataChanged.emit(self.createIndex(0, 0), self.createIndex(self.rowCount(0), self.columnCount(0)))
self.layoutChanged.emit()
def rowCount(self, parent):
return len(self.mylist)
def columnCount(self, parent):
return len(self.mylist[0])
def data(self, index, role):
if not index.isValid():
return None
if (index.column() == 0):
value = self.mylist[index.row()][index.column()].text()
else:
value = self.mylist[index.row()][index.column()]
if role == QtCore.Qt.EditRole:
return value
elif role == QtCore.Qt.DisplayRole:
return value
elif role == QtCore.Qt.CheckStateRole:
if index.column() == 0:
# print(">>> data() row,col = %d, %d" % (index.row(), index.column()))
if self.mylist[index.row()][index.column()].isChecked():
return QtCore.Qt.Checked
else:
return QtCore.Qt.Unchecked
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.header[col]
return None
def sort(self, col, order):
"""sort table by given column number col"""
# print(">>> sort() col = ", col)
if col != 0:
self.emit(SIGNAL("layoutAboutToBeChanged()"))
self.mylist = sorted(self.mylist, key=operator.itemgetter(col))
if order == Qt.DescendingOrder:
self.mylist.reverse()
self.emit(SIGNAL("layoutChanged()"))
def flags(self, index):
if not index.isValid():
return None
# print(">>> flags() index.column() = ", index.column())
if index.column() == 0:
# return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable
else:
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
def setData(self, index, value, role):
if not index.isValid():
return False
# print(">>> setData() role = ", role)
# print(">>> setData() index.column() = ", index.column())
# print(">>> setData() value = ", value)
if role == QtCore.Qt.CheckStateRole and index.column() == 0:
print(">>> setData() role = ", role)
print(">>> setData() index.column() = ", index.column())
if value == QtCore.Qt.Checked:
self.mylist[index.row()][index.column()].setChecked(True)
self.mylist[index.row()][index.column()].setText("开")
# if studentInfos.size() > index.row():
# emit StudentInfoIsChecked(studentInfos[index.row()])
else:
self.mylist[index.row()][index.column()].setChecked(False)
self.mylist[index.row()][index.column()].setText("关")
else:
print(">>> setData() role = ", role)
print(">>> setData() index.column() = ", index.column())
# self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
print(">>> setData() index.row = ", index.row())
print(">>> setData() index.column = ", index.column())
self.dataChanged.emit(index, index)
return True
def timer_func(win, mylist):
print(">>> timer_func()")
win.table_model.setDataList(mylist)
win.table_view.repaint()
win.table_view.update()
# def timer_func(num):
# print(">>> timer_func() num = ", num)
if __name__ == '__main__':
app = QApplication([])
# you could process a CSV file to create this data
header = ['开关', '只平', '期货账号', '策略编号', '交易合约', '总持仓', '买持仓', '卖持仓', '持仓盈亏', '平仓盈亏', '手续费', '净盈亏', '成交量', '成交金额', 'A成交率', 'B成交率', '交易模型', '下单算法']
# a list of (fname, lname, age, weight) tuples
checkbox1 = QtGui.QCheckBox("关");
checkbox1.setChecked(True)
dataList = [
[checkbox1, 0, '058176', '01', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '02', 'cu1705,cu1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '03', 'zn1705,zn1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '04', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '01', 'zn1705,zn1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '02', 'ru1705,ru1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '02', 'ni1705,ni1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
[QtGui.QCheckBox("关"), 0, '058176', '01', 'rb1705,rb1710', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'MA', '01'],
]
win = MyWindow(dataList, header)
win.show()
# win.table_model.setDataList(dataList)
# timer = threading.Timer(10, timer_func, (win, dataList2))
# timer.start()
app.exec_()
@ChengqiLi
Copy link

thank you, this piece of code saved my day :3

@logan4dog
Copy link

I have found this to be code showing a working pattern of a derived class inheriting PyQt base classes (QWidget). Good init methods. Good example of interface inheritance (QAbstractTableModel). Useful coding of threading, timer and emit() method.

@myrual
Copy link

myrual commented Apr 13, 2019

save my life

@nshiell
Copy link

nshiell commented Sep 20, 2019

This code is very useful, it helped me a lot

@irfanykywz
Copy link

great code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment