我正在编写一个简单的图像查看器,并实现了一个平移和缩放功能(分别使用鼠标拖动和鼠标滚轮滚动)。我成功地实现了pan(简单模式)和一个天真的“em>到左上角的”缩放。
我现在想优化缩放,使用户的鼠标在缩放时的坐标成为“焦点”:也就是说,当缩放时,平移会被更新,这样用户鼠标下的像素(图像的)保持不变(这样他们就真正地将放大到那个区域)
通过在其他普通的QWidget上覆盖paintEvent来查看图像。
尽管我可能会尝试使用直观的方法,但我似乎无法实现正确的缩放行为。在
属性scale
表示当前的缩放级别(比例为2表示图像的实际大小为原来的两倍,0.5表示为一半,scale>;0),而position
是当前查看的图像区域左上角的坐标(通过平移)。在
下面是实际图像显示的执行方式
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.drawImage(0, 0,
self.image.scaled(
self.image.width() * self.scale,
self.image.height() * self.scale,
QtCore.Qt.KeepAspectRatio),
self.position[0], self.position[1])
painter.end()
以下是平移代码(相对简单):
(pressed
和anchor
完全用于平移,并分别参考鼠标初始按下时和图像视图位置的位置)
以下是缩放代码,而不尝试调整平移。它会导致屏幕左上角的所有内容缩小或增长
def wheelEvent(self, event):
oldscale = self.scale
self.scale += event.delta() / 1200.0
if (self.scale < 0.1):
self.scale = oldscale
self.repaint()
以下是缩放代码,平移以保留(锚定)可见区域的左上角。放大时,屏幕左上角的像素不会改变。在
def wheelEvent(self, event):
oldscale = self.scale
self.scale += event.delta() / 1200
if (self.scale < 0.1):
self.scale = oldscale
self.position = (self.position[0] * (self.scale / oldscale),
self.position[1] * (self.scale / oldscale))
self.repaint()
我想要上面的效果,但是当滚动时,锚定点要在用户的鼠标上。这是我的尝试,效果非常轻微:缩放仍然不是我想要的那样,而是滚动到鼠标的一般区域,而不是锚定。事实上,将鼠标保持在相同的位置并进行放大似乎是沿着一条曲线进行的,即向右平移然后向左平移。在
def wheelEvent(self, event):
oldscale = self.scale
self.scale += event.delta() / 1200.0
if (self.scale < 0.1):
self.scale = oldscale
oldpoint = self.mapFromGlobal(QtGui.QCursor.pos())
dx, dy = oldpoint.x() - self.position[0], oldpoint.y() - self.position[1]
newpoint = (oldpoint.x() * (self.scale/oldscale),
oldpoint.y() * (self.scale/oldscale))
self.position = (newpoint[0] - dx, newpoint[1] - dy)
这背后的理论是,在缩放之前,鼠标下方的像素是左上角(位置)的长度dx和dy。缩放之后,我们计算出这个像素的新位置,并通过调整self.position
为像素的西部和北部,使其位于屏幕上相同的坐标下。在
我不完全确定我哪里出错了:我怀疑old point
到屏幕坐标的映射某种程度上是错误的,或者更可能的是:我的数学错误,因为我混淆了像素和屏幕坐标。
我尝试了一些直觉上的变化,但没有什么能接近预期的锚定。在
我想这对于文件浏览者来说是一个相当常见的任务(因为大多数人看起来都是这样缩放的),但是我发现研究这些算法相当困难。在
以下是修补缩放的完整代码(需要PyQt4):
http://pastebin.com/vvpdZy9g
感谢任何帮助!在
好吧,我设法让它工作了
这里的逻辑是:
问题确实是图像和显示坐标之间的一个小小的混淆。在
相关问题 更多 >
编程相关推荐