2010-09-23 66 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. 

再次感謝伊沃。