python - 获取相对于图像限制的鼠标位置
问题描述
我在自定义中显示图像QLabel
并点击此标签。我只对图像中的点击感兴趣,并且对由 0 到 1 之间的数字表示的位置感兴趣,0 是最左边或最上面的像素,1 是最右边或最下面的像素,无论图像的实际大小如何。
我无法获取图像矩形来计算位置。当我调用时self.pixmap.rect()
,宽度和高度是原始图像尺寸,而不是缩放以适合标签的图像尺寸。
我在做什么错?
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayout
from PyQt5.QtGui import QPixmap
class Window(QWidget):
def __init__(self):
super().__init__()
image_path = '092.jpg'
image_area = Image_Area(QPixmap(image_path))
image_area.left_click.connect(self.image_clicked)
layout = QGridLayout()
layout.addWidget(image_area, 0, 0)
self.setLayout(layout)
# Left click on image
def image_clicked(self, x, y):
print(f'{x:.3f},{y:.3f}')
class Image_Area(QLabel):
left_click = pyqtSignal(float, float)
def __init__(self, pixmap):
super().__init__()
self.pixmap = pixmap
self.setPixmap(pixmap)
self.setScaledContents(False)
self.setMinimumSize(100, 100)
def resizeEvent(self, e):
if self.pixmap != None:
width, height = int(self.width()), int(self.height())
scaled_pixmap = self.pixmap.scaled(width, height, Qt.KeepAspectRatio)
self.setPixmap(scaled_pixmap)
return super().resizeEvent(e)
def mousePressEvent(self, e):
x, y, = e.x(), e.y()
if self.pixmap:
# Get pixmap rectangle
r = self.pixmap.rect()
x0, y0 = r.x(), r.y()
x1, y1 = x0+r.width(), y0+r.height()
# Check we clicked on the pixmap
if x >= x0 and x < x1 and y >= y0 and y < y1:
# emit position relative to pixmap bottom-left corner
x_relative = (x - x0) / (x1 - x0)
y_relative = (y - y0) / (y1 - y0)
self.left_click.emit(x_relative, y_relative)
super().mousePressEvent(e)
app = QApplication([])
window = Window()
window.show()
app.exec()
更新:提供答案后,我意识到点击位置相对于图像原点的计算是错误的,这里有一个准确的版本供感兴趣的人使用:
def mousePressEvent(self, e):
# Mouse position is in label coordinates
x, y, = e.x(), e.y()
if self.pixmap():
# pixmap is not a widget, we don't have its location,
# so we assume the pixmap is centered in the label and
# compute the location with respect to label
label_size = self.size()
pixmap_size = self.pixmap().size()
width = pixmap_size.width()
height = pixmap_size.height()
x0 = int((label_size.width() - width) / 2)
y0 = int((label_size.height() - height) / 2)
# Check we clicked on the pixmap
if (x >= x0 and x < (x0 + width) and
y >= y0 and y < (y0 + height)):
# emit position relative to pixmap top-left corner
x_relative = (x - x0) / width
y_relative = (y - y0) / height
self.left_click.emit(x_relative, y_relative)
super().mousePressEvent(e)
解决方案
你必须使用QLabel中建立的QPixmap,可以通过pixmap()方法获得。问题是您混淆了对该方法的访问,因为您有一个名称相似的属性。所以解决方案是使用pixmap()
并重命名属性pixmap
。
class Image_Area(QLabel):
left_click = pyqtSignal(float, float)
def __init__(self, pixmap):
super().__init__()
self._pixmap = pixmap
self.setPixmap(pixmap)
self.setScaledContents(False)
self.setMinimumSize(100, 100)
def resizeEvent(self, e):
if self._pixmap is not None:
scaled_pixmap = self._pixmap.scaled(self.size(), Qt.KeepAspectRatio)
self.setPixmap(scaled_pixmap)
return super().resizeEvent(e)
def mousePressEvent(self, e):
x, y, = (
e.x(),
e.y(),
)
if self.pixmap:
r = self.pixmap().rect()
x0, y0 = r.x(), r.y()
x1, y1 = x0 + r.width(), y0 + r.height()
if x >= x0 and x < x1 and y >= y0 and y < y1:
x_relative = (x - x0) / (x1 - x0)
y_relative = (y - y0) / (y1 - y0)
self.left_click.emit(x_relative, y_relative)
super().mousePressEvent(e)
推荐阅读
- sabre - Sabre 入门 V3 AuthToken V3
- mysql - 如何从 mysql5 for windows 执行 os 命令?
- python - PyDev 附加到进程失败并出现“ModuleNotFoundError: No module named 'add_code_to_python_process'”
- flutter - 退出应用程序时出现数据库错误
- c - C: 使用 read() 将二进制数据读入结构数组,然后使用 qsort() 对数据进行排序
- git - 将 vb.net mvc Web 应用程序发布到本地文件夹错误“发生一个或多个错误”
- r - 模拟不平衡的集群数据
- jquery - 如何在数据表服务器端处理上禁用键盘键?
- x86 - DC PMM(内存模式)缓存一致性如何表现?
- .net - SpecFlow+LivingDoc 构建步骤在远程部署的测试运行中失败