[PyQt][Anfänger] QTableView wird nicht aktualisiert?

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Boris the Bewildered
User
Beiträge: 8
Registriert: Dienstag 28. Dezember 2010, 12:35

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 "&amp," 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_()
Antworten