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
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
Ivo. C'était ça! Je vous remercie. – bvz
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