[PyQt][Anfänger] QTableView wird nicht aktualisiert?
Verfasst: Freitag 20. April 2012, 14:08
Hallo,
ich beschäftige mich gerade mit der Model/View-Architektur von PyQt, und habe das Problem, dass die update-Methode der View nicht so zu funktionieren scheint, wie ich es erwarten würde. Der Code stellt eine 5*5-Tabelle dar sowie einen "next"-button, der einen Index-Counter erhöht. Der Custom Delegate sorgt dafür, dass die Zeile die dem Index entsrpicht durch Fettdruck hervorgehoben wird. Problem: nachdem der Index erhöht wurde, wird die View anscheinend nicht aktualisiert bzw. ändert sich jedenfalls nicht die Anzeige. Dies geschieht erst, wenn mit der Maus über das Widget gefahren wird.
Ich hatte ursprünglich versucht, sowohl die incrementIndex-Methode als auch update mit dem Next-Button zu verbinden (siehe auskommentierter Code), aber auch mit einer nextPushed-Methode, die erst die incrementIndex-Methode des Models und dann die update-Methode der View aufruft, funktioniert es nicht wie erwartet.
Wieso ist das so? Was muss ich tun, um das gewünschte Verhalten zu bekommen (Aktualisierung der Anzeige, nachdem der Index erhöht wurde)?
Edit: ich stelle gerade fest, dass ein "&" im Code durch "&," ersetzt wurde... die Zeile muss heißen " if option.state & QStyle.State_Selected:"
Und Versionsinfo: Python 2.7.2+ - Qt 4.7.4 - PyQt 4.9 on Linux
ich beschäftige mich gerade mit der Model/View-Architektur von PyQt, und habe das Problem, dass die update-Methode der View nicht so zu funktionieren scheint, wie ich es erwarten würde. Der Code stellt eine 5*5-Tabelle dar sowie einen "next"-button, der einen Index-Counter erhöht. Der Custom Delegate sorgt dafür, dass die Zeile die dem Index entsrpicht durch Fettdruck hervorgehoben wird. Problem: nachdem der Index erhöht wurde, wird die View anscheinend nicht aktualisiert bzw. ändert sich jedenfalls nicht die Anzeige. Dies geschieht erst, wenn mit der Maus über das Widget gefahren wird.
Ich hatte ursprünglich versucht, sowohl die incrementIndex-Methode als auch update mit dem Next-Button zu verbinden (siehe auskommentierter Code), aber auch mit einer nextPushed-Methode, die erst die incrementIndex-Methode des Models und dann die update-Methode der View aufruft, funktioniert es nicht wie erwartet.
Wieso ist das so? Was muss ich tun, um das gewünschte Verhalten zu bekommen (Aktualisierung der Anzeige, nachdem der Index erhöht wurde)?
Edit: ich stelle gerade fest, dass ein "&" im Code durch "&," ersetzt wurde... die Zeile muss heißen " if option.state & QStyle.State_Selected:"
Und Versionsinfo: Python 2.7.2+ - Qt 4.7.4 - PyQt 4.9 on Linux
Code: Alles auswählen
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyDelegate(QItemDelegate):
def paint(self, painter, option, index):
'''Highlight the row of the current index.
'''
if index.row() == index.model().currentIndex:
palette = QApplication.palette()
if option.state & QStyle.State_Selected:
color = QColor(QPalette().highlightedText())
bgColor = QColor(QPalette().highlight())
else:
color = QColor(QPalette().text())
if index.row() % 2 == 0:
bgColor = QColor(QPalette().base())
else:
bgColor = QColor(QPalette().alternateBase())
text = index.model().data(index).toString()
document = QTextDocument()
document.setDefaultFont(option.font)
document.setHtml(QString('<font color={0}><b>{1}<b></font>'.format(color.name(), text)))
painter.save()
painter.fillRect(option.rect, bgColor)
painter.translate(option.rect.x(), option.rect.y())
document.drawContents(painter)
painter.restore()
else:
QItemDelegate.paint(self, painter, option, index)
def sizeHint(self, option ,index):
if index.row() == index.model().currentIndex:
fm = option.fontMetrics
text = index.model().data(index).toString()
document = QTextDocument()
document.setDefaultFont(option.font)
document.setHtml(text)
return QSize(document.idealWidth() + 5, fm.height())
return QItemDelegate.sizeHint(self, option, index)
class MyModel(QAbstractTableModel):
def __init__(self, parent=None):
'''Constructor
'''
super(MyModel, self).__init__(parent)
self.currentIndex = None
def data(self, index, role=Qt.DisplayRole):
'''Return a QVariant with the data at the given index and role.
'''
if not index.isValid() or not (0 <= index.row() < 5):
return QVariant()
if role == Qt.DisplayRole:
return QVariant('{0}, {1}'.format(index.row(), index.column()))
def rowCount(self, parent=None):
return 5
def columnCount(self, parent=None):
return 5
def headerData(self, section, orientation, role=Qt.DisplayRole):
if role != Qt.DisplayRole:
return QVariant()
if orientation == Qt.Horizontal and \
section < 5:
return QVariant(section)
def incrementIndex(self):
print 'incrementing'
print self.currentIndex
if self.currentIndex == 5 - 1:
return None
elif self.currentIndex == None:
self.currentIndex = 0
else:
self.currentIndex += 1
print self.currentIndex
class MyView(QTableView):
def __init__(self, model, parent=None):
super(MyView, self).__init__(parent)
self.setModel(model)
self.setWordWrap(False)
self.setShowGrid(False)
self.setAlternatingRowColors(True)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.setSelectionBehavior(QAbstractItemView.SelectRows)
self.setItemDelegate(MyDelegate(self))
def update(self):
print 'MyView.update(): current index = {0}'.format(
self.model().currentIndex)
QTableView.update(self)
class Controller(QPushButton):
def __init__(self, model, parent=None):
QPushButton.__init__(self,parent)
self.model = model
self.setText('next')
# self.clicked.connect(self.model.incrementIndex) # the old way
# self.clicked.connect(view.update) #the old way
self.clicked.connect(self.nextIndex)
def nextIndex(self):
self.model.incrementIndex()
view.update()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
model = MyModel()
model.currentIndex = 1
view = MyView(model)
view.show()
controller = Controller(model, view)
controller.show()
app.exec_()