Python « Отображение, сортировка, доступ к данным в QTreeView. Принципы работы. [PyQt]
Здравствуйте. В приложении была необходимость выводить данные в виде списка со столбцами, для этого отлично подходил QTreeWidget, но затем понадобилась расширенная сортировка данных. После изучения методов решения выяснил, что аналогичное отображение данных + сортировку можно получить с помощью QTreeView + QSortFilterProxyModel + QStandardItemModel. В приложении используется примерно такая схема:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .python.geshi_code {font-family:monospace;} .python.geshi_code .imp {font-weight: bold; color: red;} .python.geshi_code .kw1 {color: #ff7700;font-weight:bold;} .python.geshi_code .kw2 {color: #008000;} .python.geshi_code .kw3 {color: #dc143c;} .python.geshi_code .kw4 {color: #0000cd;} .python.geshi_code .co1 {color: #808080; font-style: italic;} .python.geshi_code .coMULTI {color: #808080; font-style: italic;} .python.geshi_code .es0 {color: #000099; font-weight: bold;} .python.geshi_code .br0 {color: black;} .python.geshi_code .sy0 {color: #66cc66;} .python.geshi_code .st0 {color: #483d8b;} .python.geshi_code .nu0 {color: #ff4500;} .python.geshi_code .me1 {color: black;} .python.geshi_code span.xtra { display:block; }
# -*- encoding: utf-8 -*-
from PyQt4 import QtGui, QtCore
import sys
cNAME, cVALUE = range(2)
class SortModel(QtGui.QSortFilterProxyModel):
def lessThan(self, left, right):
leftData = self.sourceModel().data(left)
rightData = self.sourceModel().data(right)
if self.sortColumn() == cVALUE:
return int(leftData) < int(rightData)
else:
return leftData < rightData
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.centralWidget = QtGui.QWidget()
self.setCentralWidget(self.centralWidget)
self.modelData = QtGui.QStandardItemModel(0, 2)
self.modelData.setHorizontalHeaderLabels(['Столбец1', 'Столбец2'])
self.modelData.appendRow([QtGui.QStandardItem('10'), QtGui.QStandardItem('2')])
self.modelData.appendRow([QtGui.QStandardItem('20'), QtGui.QStandardItem('40')])
self.modelData.appendRow([QtGui.QStandardItem('3'), QtGui.QStandardItem('7')])
self.sortModel = SortModel()
self.sortModel.setDynamicSortFilter(True)
self.sortModel.setSortCaseSensitivity(False)
self.sortModel.setSourceModel(self.modelData)
self.treeView = QtGui.QTreeView(self.centralWidget)
self.treeView.setGeometry(QtCore.QRect(10,10, 430,300))
self.treeView.setModel(self.sortModel)
self.treeView.setSortingEnabled(True)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.treeView)
self.setLayout(mainLayout)
self.resize(500, 450)
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
И тут возникли следующие вопросы:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .python.geshi_code {font-family:monospace;} .python.geshi_code .imp {font-weight: bold; color: red;} .python.geshi_code .kw1 {color: #ff7700;font-weight:bold;} .python.geshi_code .kw2 {color: #008000;} .python.geshi_code .kw3 {color: #dc143c;} .python.geshi_code .kw4 {color: #0000cd;} .python.geshi_code .co1 {color: #808080; font-style: italic;} .python.geshi_code .coMULTI {color: #808080; font-style: italic;} .python.geshi_code .es0 {color: #000099; font-weight: bold;} .python.geshi_code .br0 {color: black;} .python.geshi_code .sy0 {color: #66cc66;} .python.geshi_code .st0 {color: #483d8b;} .python.geshi_code .nu0 {color: #ff4500;} .python.geshi_code .me1 {color: black;} .python.geshi_code span.xtra { display:block; }
# -*- encoding: utf-8 -*-
from PyQt4 import QtGui, QtCore
import sys
cNAME, cVALUE = range(2)
class SortModel(QtGui.QSortFilterProxyModel):
def lessThan(self, left, right):
leftData = self.sourceModel().data(left)
rightData = self.sourceModel().data(right)
if self.sortColumn() == cVALUE:
return int(leftData) < int(rightData)
else:
return leftData < rightData
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.centralWidget = QtGui.QWidget()
self.setCentralWidget(self.centralWidget)
self.modelData = QtGui.QStandardItemModel(0, 2)
self.modelData.setHorizontalHeaderLabels(['Столбец1', 'Столбец2'])
self.modelData.appendRow([QtGui.QStandardItem('10'), QtGui.QStandardItem('2')])
self.modelData.appendRow([QtGui.QStandardItem('20'), QtGui.QStandardItem('40')])
self.modelData.appendRow([QtGui.QStandardItem('3'), QtGui.QStandardItem('7')])
self.sortModel = SortModel()
self.sortModel.setDynamicSortFilter(True)
self.sortModel.setSortCaseSensitivity(False)
self.sortModel.setSourceModel(self.modelData)
self.treeView = QtGui.QTreeView(self.centralWidget)
self.treeView.setGeometry(QtCore.QRect(10,10, 430,300))
self.treeView.setModel(self.sortModel)
self.treeView.setSortingEnabled(True)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.treeView)
self.setLayout(mainLayout)
self.resize(500, 450)
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
И тут возникли следующие вопросы:
- Как правильно получать исходные данные?
сейчас для того чтобы получить данные какого-либо столбца при выборе строки в списке использую код:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .python.geshi_code {font-family:monospace;} .python.geshi_code .imp {font-weight: bold; color: red;} .python.geshi_code .kw1 {color: #ff7700;font-weight:bold;} .python.geshi_code .kw2 {color: #008000;} .python.geshi_code .kw3 {color: #dc143c;} .python.geshi_code .kw4 {color: #0000cd;} .python.geshi_code .co1 {color: #808080; font-style: italic;} .python.geshi_code .coMULTI {color: #808080; font-style: italic;} .python.geshi_code .es0 {color: #000099; font-weight: bold;} .python.geshi_code .br0 {color: black;} .python.geshi_code .sy0 {color: #66cc66;} .python.geshi_code .st0 {color: #483d8b;} .python.geshi_code .nu0 {color: #ff4500;} .python.geshi_code .me1 {color: black;} .python.geshi_code span.xtra { display:block; }
def on_treeView_pressed(self, current):
data = current.sibling(current.row(), 0).data(QtCore.Qt.DisplayRole)
- Необходимо реализовать такое поведение: например, если значение в строке в столбце 2 больше, чем в столбце 1, то надо выделить всю строку жирным шрифтом. Пробовал в классе, наследованном от QSortFilterProxyModel переопределить метод data, но там соответственно столкнулся с проблемой выборки данных, максимум что получалось - это то, что нужные строки выделялись жирным, но список переставал сортироваться, видимо потому, что данные выдирал прямо из QStandardItemModel, получалось так, что они выводятся в QTreeView в таком порядке, в котором они находятся в QStandardItemModel .