2012-01-20 25 views
1

我在加載到QGraphicsViewQGraphicsPixmapItem的縮放TIFF圖像時遇到問題。在交換圖像時維護QGraphicsView中的視圖/滾動位置

問題是更多的維護圖像質量以及具有不會導致應用程序窒息的縮放速度。首先,我只是用縮放QPixmap替換圖像 - 我用Qt.FastTransformation,而用戶按住水平滑塊,然後釋放滑塊時,再次用另一個縮放的像素圖替換像素圖,使用Qt.SmoothTransformation。這給了一個很好的質量放大的圖像,但縮放後圖像尺寸開始增加到大於其原始大小後變得不穩定;縮小圖像很好。

即使在QGraphicsView中應用.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.HighQualityAntialiasing)時,在QGraphicsView上使用QTransform.fromScale()可以獲得更平滑的縮放效果,但質量較差。

我的最新的方法是將兩種方法結合起來,並使用QTransformQGraphicsView有平滑縮放,但是當用戶釋放滑塊與縮放像素圖替換QGraphicsView圖像。這很好,但視圖中的位置丟失了 - 用戶放大到一個區域,並且由於縮放後的像素圖較大,視圖在釋放滑塊時跳轉到另一個位置,並且質量較高的縮放像素替換先前的圖像。

我認爲,因爲兩幅圖像中的寬高比是相同的,所以我可以在圖像交換之前取得滾動條的百分比,並在交換之後應用相同的百分比,並且事情應該很好。這主要適用於大多數情況,但仍然有時候交換圖像後視圖「跳躍」。

我很確定我在這裏做的事情相當不對。是否有人知道更好的方法來做到這一點,或者任何人都可以在下面的代碼中找到可能導致跳躍的東西?

這是保存/恢復滾動條位置的代碼。他們是一個子類QGraphicsView的方法:

def store_scrollbar_position(self): 
    x_max = self.horizontalScrollBar().maximum() 
    if x_max: 
     x = self.horizontalScrollBar().sliderPosition() 
     self.scroll_x_percentage = x * (100/float(x_max)) 

    y_max = self.verticalScrollBar().maximum() 
    if y_max: 
     y = self.verticalScrollBar().sliderPosition() 
     self.scroll_y_percentage = y * (100/float(y_max)) 


def restore_scrollbar_position(self): 
    x_max = self.horizontalScrollBar().maximum() 
    if self.scroll_x_percentage and x_max: 
     x = x_max * (float(self.scroll_x_percentage)/100) 
     self.horizontalScrollBar().setSliderPosition(x) 

    y_max = self.verticalScrollBar().maximum() 
    if self.scroll_y_percentage and y_max: 
     y = y_max * (float(self.scroll_y_percentage)/100) 
     self.verticalScrollBar().setSliderPosition(y) 

這裏就是我正在做的縮放。 self.imageFileQPixmapself.image是我的QGraphicsPixmapItem。再次,是子類別QGraphicsView的一部分。該方法附加到滑塊移動,highQuality參數設置爲False。它在滑動釋放時被再次調用,highQuality作爲True來交換圖像。

def setImageScale(self, scale=None, highQuality=True): 
    if self.imageFile.isNull(): 
     return 
    if scale is None: 
     scale = self.scale 
    self.scale = scale 

    self.image.setPixmap(self.imageFile) 
    self.scene.setSceneRect(self.image.boundingRect()) 
    self.image.setPos(0, 0) 
    if not highQuality: 
     self.setTransform(QTransform.fromScale(self.scaleFactor, self.scaleFactor)) 
     self.store_scrollbar_position() 
    else: 
     self.image.setPixmap(self.imageFile.scaled(self.scaleFactor * self.imageFile.size(), 
                Qt.KeepAspectRatio, Qt.SmoothTransformation)) 
     self.setTransform(self.transform) 
     self.scene.setSceneRect(self.image.boundingRect()) 
     self.image.setPos(0, 0) 
     self.restore_scrollbar_position() 
    return 

任何幫助,將不勝感激。現在我開始對此感到非常沮喪。

回答

1

我發現了一個比我第一次發佈的代碼更好的解決方案。它還不完美,但有很大的改進。萬一別人正在努力解決類似的問題...

當設置低質量的圖像我把這個方法添加到我的QGraphicsView:

def get_scroll_state(self): 
    """ 
    Returns a tuple of scene extents percentages. 
    """ 
    centerPoint = self.mapToScene(self.viewport().width()/2, 
            self.viewport().height()/2) 
    sceneRect = self.sceneRect() 
    centerWidth = centerPoint.x() - sceneRect.left() 
    centerHeight = centerPoint.y() - sceneRect.top() 
    sceneWidth = sceneRect.width() 
    sceneHeight = sceneRect.height() 

    sceneWidthPercent = centerWidth/sceneWidth if sceneWidth != 0 else 0 
    sceneHeightPercent = centerHeight/sceneHeight if sceneHeight != 0 else 0 
    return sceneWidthPercent, sceneHeightPercent 

這被存儲在self.scroll_state。當設置高質量圖像時,我調用另一個函數來恢復前一個函數中使用的百分比。

def set_scroll_state(self, scroll_state): 
    sceneWidthPercent, sceneHeightPercent = scroll_state 
    x = (sceneWidthPercent * self.sceneRect().width() + 
     self.sceneRect().left()) 
    y = (sceneHeightPercent * self.sceneRect().height() + 
     self.sceneRect().top()) 
    self.centerOn(x, y) 

這將中心位置設置爲與交換圖像之前相同的位置(百分比)。