2010-09-23 3 views
2

Je vais essayer d'être aussi clair que possible, même si tout cela est un peu embrouillé dans ma tête.PyQt QTableView ne pas afficher les icônes après la mise à jour de PyQt 4.5.1

J'ai une application PyQt qui fonctionne depuis environ un an maintenant. Après la mise à jour vers PyQt 4.5.1 (à partir de 4.3.3), aucune de mes icônes n'apparaît plus dans QTableView (cette mise à jour était concomitante avec une mise à jour de python 2.6.5 à partir de la version 2.5.1). Revenir à l'ancien python et PyQt, tout fonctionne comme prévu.

La répartition est la suivante:

J'utilise la méthodologie modèle-vue. Mon modèle, lorsqu'il est demandé via un Qt.DecorationRole dans la méthode data(), retournera un objet personnalisé (ColorSwatch) qui est une sous-classe de la classe QIcon. Cela a toujours fonctionné (avec la mise en garde que, pour des raisons que je ne comprends pas, je dois le refondre comme un QVariant d'abord). Après la mise à jour vers PyQt 4.5.1, apparaît pour fonctionner correctement (c'est-à-dire que je ne reçois aucune erreur), mais l'icône ne dessine pas (bien que l'espace où elle serait dessinée soit "réservé" le droit de faire place à cette icône invisible).

Voici quelques choses que j'ai essayé:

J'ai vérifié que la classe ColorSwatch ne fonctionne toujours. Cette même classe est utilisée pour dessiner des icônes dans un menu contextuel - et elles apparaissent correctement.

J'ai vérifié que la méthode data() est réellement appelée et retourne cet objet ColorSwatch (refonte dans un QVariant < - bien que j'ai aussi testé sans cette refonte).

Verser du sang de serpent sur mon clavier et l'allumer.

Rien jusqu'à présent ne m'a donné aucune idée de ce que je devrais faire. Tous les conseils seraient grandement appréciés. Merci.

Voici quelques-unes des (potentiellement) code approprié (notez que paramObj.get_icon() retourne un objet ColorSwatch):

#--------------------------------------------------------------------------- 
def data(self, index, role=QtCore.Qt.DisplayRole): 
    """ 
    Returns the text or formatting for a particular cell, depending on the 
    role supplied. 
    """ 


    blah 
    blah 
    blah 



    elif role == QtCore.Qt.DecorationRole: 
     if platform.system()=='Darwin': 
      return QtGui.QIcon(paramObj.get_icon()) 
     else: 
      return QtCore.QVariant(paramObj.get_icon()) 

et

import os 
import tempfile 
import sys 
import colorsys 
import copy 
import fnmatch 
import time 

from PyQt4 import QtGui 
from PyQt4 import QtCore 


################################################################################ 
class ColorSwatch(QtGui.QIcon): 
    """ 
    A subclass of QIcon, this class draws a colored paint chip with a border 
    The color and size are determined at construction time, and cannot 
    be changed later. 
    """ 

    #--------------------------------------------------------------------------- 
    def __init__(self, r=1, g=1, b=1, br = 0, bg = 0, bb = 0, w=20, h=20): 
     """ 
     Constructor for the ColorSwatch class. Takes the passed arguments and 
     creates a square icon filled with the given color and with a border 
     color determined by br, bg, bb. All colors should be in floating point 
     format. 
     """ 
     QtGui.QIcon.__init__(self) 

     #normalize the color 
     r8, g8, b8 = self.normalize_color((r, g, b)) 

     #convert the r, g, b values to 8 bit colors 
     r8, g8, b8 = self.fp_to_8b_color((r8, g8, b8)) 

     #Create the pixmap and painter objects 
     paintChip = QtGui.QPixmap(w, h) 
     painter = QtGui.QPainter() 
     painter.begin(paintChip) 

     #fill the swatch 
     baseColor = QtGui.QColor(r8, g8, b8) 
     painter.fillRect(0, 0, w, h, baseColor) 

     #if any of the values were super brights (>1), draw a smaller, white 
     #box inset to make sure the user knows 
     if r > 1 or g > 1 or b > 1: 
      painter.fillRect(5, 5, w-10, h-10, QtGui.QColor(255, 255, 255)) 

     #if all values are 0, put a faint x through the icon 
# # #   brush = QtGui.QBrush() 
# # #   brush.setColor(QtGui.QColor(30, 30, 30)) 
     painter.setPen(QtGui.QColor(200, 200, 200)) 
     if r ==0 and g == 0 and b == 0: 
      painter.drawLine(0, 0, w, h) 
      painter.drawLine(w-1, 0, -1, h) 
# # #   
# # #   #normalize the color 
# # #   r8, g8, b8 = self.normalize_color((r8, g8, b8)) 

     #now draw the border(s) 
     #convert the r, g, b values to 8 bit colors 
     r8, g8, b8 = self.fp_to_8b_color((br, bg, bb)) 

     #draw the border 
     painter.setPen(QtGui.QColor(r8, g8, b8)) 
     painter.drawRect(0,0,w-1,h-1) 

     #if any of the values were super brights (>1), draw a border around the 
     #inset box as well. 
     if r > 1 or g > 1 or b > 1: 
      painter.drawRect(5,5,w-11,h-11) 

     #done drawing 
     painter.end() 

     #add it (both to the normal and the selected modes) 
     self.addPixmap(paintChip, QtGui.QIcon.Normal) 
     self.addPixmap(paintChip, QtGui.QIcon.Selected) 


    #--------------------------------------------------------------------------- 
    def fp_to_8b_color(self, color): 
     """ 
     Convert a floating point color value (passed in the form of a three 
     element tuple) to a regular 8-bit 0-255 value. Returns a 3 item tuple. 
     """ 
     r = max(min(int(color[0]*255),255),0) 
     g = max(min(int(color[1]*255),255),0) 
     b = max(min(int(color[2]*255),255),0) 
     return (r,g,b) 


    #--------------------------------------------------------------------------- 
    def normalize_color(self, color): 
     """ 
     "normalizes" a color value so that if there are any super-whites, it 
     balances all the other floating point values so that we end up with a 
     "real" color. Negative values will result in undefined behavior. 
     Mainly used to make the color chip "look right" when using super whites. 
     """ 
     maxValue = max(color) 
     if maxValue > 1: 
      return (color[0]/maxValue, color[1]/maxValue, color[2]/maxValue) 
     else: 
      return color 
+0

Je sais qu'une partie du casting automatique de/vers QVariant a changé à plusieurs reprises dans le passé avec PyQt. Essayez ceci: QVariant (QIcon (paramObj.get_icon())). Aussi, pourquoi avez-vous le chèque pour Darwin là-bas? – Ivo

+0

Ivo. C'était ça! Je vous remercie. – bvz

+0

Incidemment, je vérifie pour Darwin parce que, au moment où je développais initialement cela, j'ai trouvé par essais et erreurs qu'OSX n'afficherait les icônes que s'il était retourné comme QIcon, et Linux ne fonctionnerait que s'il renvoyait un QVariant . Cela fait un moment que je l'ai couru sous OSX et je ne sais pas si c'est toujours le cas. Merci encore pour votre aide! – bvz

Répondre

1

Ivo a répondu à ma question ci-dessus.

le code réel qui fonctionne est:

#--------------------------------------------------------------------------- 
def data(self, index, role=QtCore.Qt.DisplayRole): 
    """ 
    Returns the text or formatting for a particular cell, depending on the 
    role supplied. 
    """ 


    blah 
    blah 
    blah 



    elif role == QtCore.Qt.DecorationRole: 
     if platform.system()=='Darwin': 
      return QtGui.QIcon(paramObj.get_icon()) 
     else: 
      return QtCore.QVariant(QtGui.QIcon(paramObj.get_icon())) 
      #Note that it is first cast as a QIcon before 
      #being cast as a QVariant. 

Merci encore Ivo.