Форум сайта python.su
Подскажите пожалуйста как у QAbstractTableModel реализовать метод setHeaderData. Второй день бьюсь, ни чего не получается.
Офлайн
Что конкретно нужно? Что конкретно не получается? И где конкретный код? :)
Офлайн
Опишу поподробней задачу. Нас интересует вертикальный заголовок QTableView - нужна простая нумерация строк по порядку, вдобавок она должна оставаться правильной при включенной сортировке по заголовку столбца. Т.е. всегда 1,2,3,4,5….100… Если делаю так как в коде ниже, получается черт знает что, а не нумерация по порядку. Я хотел создавать вертикальный заголовок в цикле уже после формирования модели в TableView, методом setHeaderData(), но насколько я понял у QAbstractTableModel этот метод не организован (нужно создавать самому), чтото типа:
def setHeaderData(self, section, orientation, value, role):
if …….:
.
.
.
model.headerDataChanged.emit(orientation, section, section)
return True
else:
return False
Вот с наполнением функции у меня полная непонятка.
В интернете не нашел ни одного примера реализации этого метода.
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
class MyWindow(QtGui.QWidget):
def __init__(self, *args):
QtGui.QWidget.__init__(self, *args)
table = self.createTable()
layout = QtGui.QVBoxLayout()
layout.addWidget(table)
self.setLayout(layout)
def createTable(self):
tv = QtGui.QTableView()
tm = MyTableModel(self)
# set the proxy model
pm = QtGui.QSortFilterProxyModel(self)
pm.setSourceModel(tm)
tv.setModel(pm)
tv.setMinimumSize(400, 300)
# show vertical header
tv.verticalHeader().setVisible(True)
# Сортировка по щелчку на заголовке столбца
tv.setSortingEnabled(True)
tv.sortByColumn(0, QtCore.Qt.AscendingOrder)
return tv
class MyTableModel(QtCore.QAbstractTableModel):
def __init__(self, parent=None, *args):
QtCore.QAbstractTableModel.__init__(self, parent, *args)
self.colLabels = ['Col1', 'Col2', 'Col3', 'Col4', 'Col5']
self.cached = [
['89','cell12','cell13','cell14','cell15',],
['34','cell22','cell23','cell24','cell25',],
['56','cell32','cell33','cell34','cell35',],
['18','cell42','cell43','cell44','cell45',],
['22','cell52','cell53','cell54','cell55',],
['44','cell62','cell63','cell64','cell65',],
['19','cell72','cell73','cell74','cell75',],
['76','cell82','cell83','cell84','cell85',],
]
def rowCount(self, parent):
return len(self.cached)
def columnCount(self, parent):
return len(self.colLabels)
def data(self, index, role):
if not index.isValid():
return QtCore.QVariant()
elif role != QtCore.Qt.DisplayRole and role != QtCore.Qt.EditRole:
return QtCore.QVariant()
value = ''
if role == QtCore.Qt.DisplayRole:
row = index.row()
col = index.column()
value = self.cached[row][col]
return QtCore.QVariant(value)
def headerData(self, section, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return QtCore.QVariant(self.colLabels[section])
#заголовки строк
if orientation == QtCore.Qt.Vertical and role == QtCore.Qt.DisplayRole:
return QtCore.QVariant("%s" % str(section + 1))
return QtCore.QVariant()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
Офлайн
Урмх. Как-то все это странно выглядит. QAbstractTableModel - абстрактный класс (ооп термин абстрактный класс знаком?) который используется для определения списка методов, которые должны быть реализованы. Т.е. QTableView является наследником QAbstractTableModel и определяет метод setHeaderData так, как это необходимо для нормальной работы. Если MyTableModel наследовать от QTableModel, то не придется самому писать метод setHeaderData. Посмотрите примеры к PyQt там вроде должна быть нумерация строк. Там вроде вообще наследуется от QSqlQueryModel. Одним словом думаю вас куда-то не туда занесло.
Офлайн
dartNNNИли я Вас не понял, или…. Это что за класс “QTableModel” - не нашел такого. Можно подробнее.
Если MyTableModel наследовать от QTableModel, то не придется самому писать метод setHeaderData.
dartNNNВот пример из документации “sql” - “cachedtable.py”, добавлена только сортировка щелчком по заголовку столбца. Модуль connection стандартный из документации. И теперь смотрим - и видим, что нумерация строк работает так же криво. Да и почему нельзя переопределить метод setHeaderData, ведь мы же реализуем headerData, data, setData и т.д. Вот я и интересуюсь возможностью такой реализации. Если я гдето ошибаюсь, прошу направить на путь истинный, т.к. с QT работаю всего второй месяц.
Посмотрите примеры к PyQt там вроде должна быть нумерация строк. Там вроде вообще наследуется от QSqlQueryModel. Одним словом думаю вас куда-то не туда занесло.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui, QtSql
import connection
class TableEditor(QtGui.QDialog):
def __init__(self, tableName, parent=None):
super(TableEditor, self).__init__(parent)
self.model = QtSql.QSqlTableModel(self)
self.model.setTable(tableName)
self.model.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit)
self.model.select()
self.model.setHeaderData(0, QtCore.Qt.Horizontal, "ID")
self.model.setHeaderData(1, QtCore.Qt.Horizontal, "First name")
self.model.setHeaderData(2, QtCore.Qt.Horizontal, "Last name")
self.pm = QtGui.QSortFilterProxyModel(self)
self.pm.setSourceModel(self.model)
view = QtGui.QTableView()
view.setModel(self.pm)
# Сортировка по щелчку на заголовке столбца
view.setSortingEnabled(True)
view.sortByColumn(0, QtCore.Qt.AscendingOrder)
submitButton = QtGui.QPushButton("Submit")
submitButton.setDefault(True)
revertButton = QtGui.QPushButton("&Revert")
quitButton = QtGui.QPushButton("Quit")
buttonBox = QtGui.QDialogButtonBox(QtCore.Qt.Vertical)
buttonBox.addButton(submitButton, QtGui.QDialogButtonBox.ActionRole)
buttonBox.addButton(revertButton, QtGui.QDialogButtonBox.ActionRole)
buttonBox.addButton(quitButton, QtGui.QDialogButtonBox.RejectRole)
submitButton.clicked.connect(self.submit)
revertButton.clicked.connect(self.model.revertAll)
quitButton.clicked.connect(self.close)
mainLayout = QtGui.QHBoxLayout()
mainLayout.addWidget(view)
mainLayout.addWidget(buttonBox)
self.setLayout(mainLayout)
self.setWindowTitle("Cached Table")
def submit(self):
self.model.database().transaction()
if self.model.submitAll():
self.model.database().commit()
else:
self.model.database().rollback()
QtGui.QMessageBox.warning(self, "Cached Table",
"The database reported an error: %s" % self.model.lastError().text())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
if not connection.createConnection():
sys.exit(1)
editor = TableEditor('person')
editor.show()
sys.exit(editor.exec_())
Офлайн
Bujhm666Упс очепятка:) Извиняюсь. Имел ввиду QTableView
Это что за класс “QTableModel”
Bujhm666Я не говорил, что нельзя. Я имел ввиду, что это вовсе не обязательно в рамках данной проблемы. Признаюсь, что не знаю как надо правильно переопределять setHeaderData()
Да и почему нельзя переопределить метод setHeaderData
Офлайн
dartNNNНет наверно вы меня не поняли. Мне надо чтобы нумерация строк всегда (при любой сортировке) было по порядку сверху вниз (1234567…….). Т.е чтобы заголовки строк не принимали участия в сортировке.
Но я не понимаю, чего такого кривого в стандартной нумерации строк? Самая верхняя строка всегда под номером 1. Если вам надо, чтобы строка всегда сохраняла свой номер после сортировки (я правильно понял?), то проще (по-моему) использовать дополнительное поле в записи или как нибудь так.
Офлайн
Привет товарищи! у меня возник тоже вот такой вопрос:
пишу вот эту строчку для QTableView:
self.my_table.setSortingEnabled(True)
Полазив в дезайнере(для QTableWidget), как я понял, именно она и включает возможность сортировки,кликая по заголовку таблице?
Но если в QTableWidget там уже автоматически работает сортировка для каждого заголовка столбца, то как абстоит дело в QTableView?
Получается нужно еще самому мутить сигнал и слот?типа
self.my_table.horizontalHeader().sectionClicked.connect()
или какой сигнал использовать?
Офлайн
Выше два примера, в обоих присутствует сортировка при клике на заголовок столбца. Нужно использовать QSortFilterProxyModel и включить сортировку для QTableView. Там буквально 4 строчки - разберетесь.
Офлайн
То-то и оно)),но почему для QTableWidget все по-другому, хотя если не ошибаюсь QTableView наследуется от QTableWidget, то все должно быть по-аналогии зачем такие замуты?или я чего то не понимаю))Посмотри в дизайнере для QTableWidget как это работает,там не надо никаких проксифильтр!
Офлайн