2010-09-23 68 views
2

我会尽量清楚,尽管这在我的脑海中有点混乱。PyQt QTableView在更新到PyQt 4.5.1后不显示图标

我有一个已经工作了大约一年的PyQt应用程序。在更新到PyQt 4.5.1(从4.3.3开始)后,我的图标不再出现在QTableView中(此更新与2.5.1中的python 2.6.5更新并发)。恢复到较旧的python和PyQt,一切都按预期工作。

故障是这样的:

我正在使用模型视图方法。我的模型,当通过data()方法中的Qt.DecorationRole请求时,将返回一个自定义对象(ColorSwatch),它是QIcon类的一个子类。这一直都很有效(我要提醒的是,由于我不明白的原因,我必须先将它重新改写为QVariant)。更新到PyQt 4.5.1后,它出现正确运行(即我没有得到任何错误),但图标不绘制(虽然它将被绘制的空间是“保留”,即文本已被转移到让这个隐形图标让路的权利)。

这里有一些事情,我曾尝试:

我已经验证ColorSwatch类确实仍然起作用。这个类用于将图标绘制到上下文菜单中 - 并且它们正确显示。

我已经验证data()方法实际上正在调用并且正在返回此ColorSwatch对象(重新转换为QVariant < - 尽管我已经测试过这种方法没有这种重新设计)。

将蛇血倒在我的键盘上并点燃它。

到目前为止,没有任何线索告诉我应该做什么。任何提示将不胜感激。谢谢。

下面是一些(潜在的)相关代码(注意paramObj.get_icon()返回一个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()) 

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

我知道一些从QVariant转换到QVariant的自动转换已经在PyQt的过去几个时间点上发生了变化。试试这个:QVariant(QIcon(paramObj.get_icon()))。另外,你为什么要在那里检查达尔文? – Ivo 2010-09-23 10:04:37

+0

Ivo。就是这样!谢谢。 – bvz 2010-09-23 16:23:06

+0

顺便说一下,我正在检查Darwin,因为在我最初开发这个时候,我发现通过试验和错误,OSX只会显示图标,如果它是作为QIcon返回的,并且linux只有在返回QVariant 。我在OSX上运行它已经有一段时间了,但不知道是否仍然如此。再次感谢你的帮助! – bvz 2010-09-23 16:27:24

回答

1

伊沃上述回答我的问题。

,工程实际的代码是:

#--------------------------------------------------------------------------- 
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. 

再次感谢伊沃。