如何获取已加载图像的坐标而不是显示

时间:2018-05-16 20:37:46

标签: python pyqt5 qgraphicsview qgraphicsitem pyside2

我正在使用按钮处理图像查看器,以便在单击时获取已加载图像的坐标。但是,当我放大图像并单击它时,我得到图像所在的显示坐标,与图像在正方形内居中的位置无关。我想得到的是加载图像的点击坐标。这意味着如果显示器中的图像是缩放或滚动(上/下或右/左),则坐标应相应地适应。这可能是一个容易回答的简单问题但是,尽管我试图理解Qt website的文档没有成功,但我已经停留了一个多星期的问题

例如,我试图替换

self.photo_clicked.emit(QtCore.QPoint(event.pos()))

通过

self.photo_clicked.emit(QtCore.QPoint(QGraphicsView.mapFromScene(event.pos())))

但它给了我这个错误:

TypeError: descriptor 'mapFromScene' requires a 'PySide2.QtWidgets.QGraphicsView' object but received a 'PySide2.QtCore.QPoint'

这是脚本(部分内容受this example启发):

from PySide2.QtWidgets import (QWidget, QApplication, QSlider,
        QGraphicsView, QGraphicsScene, QVBoxLayout)
from PySide2.QtGui import QPainter, QColor
from PySide2 import QtCore, QtWidgets, QtGui
from PySide2.QtOpenGL import *
from PySide2.QtCore import *
from PySide2.QtGui import *
import sys

image_path_str='image.jpg'

class View(QGraphicsView):
    photo_clicked = QtCore.Signal(QtCore.QPoint)

    def __init__(self, parent):
        super(View, self).__init__()
        self.scene = QtWidgets.QGraphicsScene(self)
        self.photo = QtWidgets.QGraphicsPixmapItem()
        self.scene.addItem(self.photo)
        pixmap = QtGui.QPixmap(image_path_str)
        self.photo.setPixmap(pixmap)
        self.setScene(self.scene)
        self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)

    def Hand_drag(self):
            self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)

    def pixel_pointer(self):
            self.setDragMode(QtWidgets.QGraphicsView.NoDrag)

    def mousePressEvent(self, event):
        if self.photo.isUnderMouse():
                self.photo_clicked.emit(QtCore.QPoint(event.pos()))

        super(View, self).mousePressEvent(event)

class Window(QWidget):

    def __init__(self):
        super(Window, self).__init__()
        self.view = View(self)

        self.btn_hand_drag = QtWidgets.QCheckBox("Hand drag", self)
        self.btn_hand_drag.clicked.connect(self.view.Hand_drag)
        self.btn_hand_drag.clicked.connect(self.btn_hand_drag_uncheck_others)

        self.btn_pix_info1 = QtWidgets.QCheckBox("Point 1", self)
        self.btn_pix_info1.clicked.connect(self.view.pixel_pointer)
        self.btn_pix_info1.clicked.connect(self.btn_pix_info1_drag_uncheck_other)
        self.editPixInfo1 = QtWidgets.QLineEdit(self)
        self.editPixInfo1.setReadOnly(True)

        self.btn_pix_info2 = QtWidgets.QCheckBox("Point 2", self)
        self.btn_pix_info2.clicked.connect(self.view.pixel_pointer)
        self.btn_pix_info2.clicked.connect(self.btn_pix_info2_drag_uncheck_other)
        self.editPixInfo2 = QtWidgets.QLineEdit(self)
        self.editPixInfo2.setReadOnly(True)

        self.view.photo_clicked.connect(self.photo_clicked)

        slider = QSlider(Qt.Horizontal, self)
        slider.setRange(1, 500)
        slider.setValue(100)
        slider.valueChanged[int].connect(self.zoom)

        vbox = QVBoxLayout()
        vbox.addWidget(self.btn_hand_drag)
        vbox.addWidget(self.btn_pix_info1)
        vbox.addWidget(self.editPixInfo1)
        vbox.addWidget(self.btn_pix_info2)
        vbox.addWidget(self.editPixInfo2)
        vbox.addWidget(self.view)
        vbox.addWidget(slider)

        self.setLayout(vbox)
        self.setWindowTitle("Image viewer")
        self.setGeometry(200, 200, 1000, 800)

    def zoom(self, value):
        val = value / 100
        self.view.resetTransform()
        self.view.scale(val, val)

    def btn_hand_drag_uncheck_others(self):
        self.btn_pix_info1.setChecked(False)
        self.btn_pix_info2.setChecked(False)

    def btn_pix_info1_drag_uncheck_other(self):
        self.btn_hand_drag.setChecked(False)
        self.btn_pix_info2.setChecked(False)

    def btn_pix_info2_drag_uncheck_other(self):
        self.btn_hand_drag.setChecked(False)
        self.btn_pix_info1.setChecked(False)

    def photo_clicked(self, pos):
        if self.btn_pix_info1.isChecked():
                self.editPixInfo1.setText('%d, %d' % (pos.x(), pos.y()))
        if self.btn_pix_info2.isChecked():
                self.editPixInfo2.setText('%d, %d' % (pos.x(), pos.y()))

app = QApplication.instance()
if app is None:
        app = QApplication([])
w = Window()
w.show()
w.raise_()
app.exec_()

1 个答案:

答案 0 :(得分:2)

当您缩放并按下像素时,这可以表示一组像素,反之亦然,我想您明白,因为根据具体情况显示图像是下采样或上移。所以最后,不管它是什么,你都会得到一个不太理想但非常接近的像素。说到这一点,考虑到在@ekhumuro的实现中没有项目的升级,相对于项目的坐标系而不是场景使用鼠标位置是正确的,因为项目可以移动,所以考虑到项目未被转换的一般解决方案是:

def mousePressEvent(self, event):
    if self._photo.isUnderMouse():
        p = self._photo.mapToItem(self._photo, self.mapToScene(event.pos()))
        self.photoClicked.emit(p.toPoint())
    super(PhotoViewer, self).mousePressEvent(event)