我在使用QGraphicsPixmapItem
缩放加载到QGraphicsView
中的TIFF图像时遇到了问题。
问题更多的是保持图像质量,同时拥有不会使应用程序卡住的变焦速度。首先,我只是用缩放的QPixmap
替换图像-当用户按下水平滑块时,我使用了Qt.FastTransformation
,然后当滑块被释放时,再次使用Qt.SmoothTransformation
将像素图替换为另一个缩放的像素图。这提供了一个很好的质量的缩放图像,但在图像大小开始增加到大于其原始大小后,缩放变得不稳定;缩小图像是很好的。
在QGraphicsView上使用QTransform.fromScale()可以获得更平滑的缩放效果,但图像质量较低,即使在将.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.HighQualityAntialiasing)
应用于QGraphicsView时也是如此。
我的最新方法是结合使用这两种方法,并在QGraphicsView
上使用QTransform
来实现平滑缩放,但是当用户释放滑块时,会用缩放后的像素图替换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.imageFile
是QPixmap
,self.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
任何帮助都将不胜感激。我现在开始对此感到非常沮丧了。
发布于 2012-03-09 16:10:53
我找到了一个比我第一次发布的代码工作得更好的解决方案。它仍然不完美,但已经有了很大的改进。以防其他人也想解决类似的问题...
当设置低质量图像时,我调用此方法添加到我的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)
这会将中心位置设置为与交换图像之前相同的位置(百分比)。
https://stackoverflow.com/questions/8939315
复制