简体   繁体   English

如何使用 PyQt5 获取像素位置并在该位置绘制一个点?

[英]How to get pixel location and draw a dot on that location using PyQt5?

from PyQt5 import QtCore, QtGui, QtWidgets

class Window(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        layout = QtWidgets.QGridLayout(self)

        self.getImageButton = QtWidgets.QPushButton('Select')
        layout.addWidget(self.getImageButton)
        self.getImageButton.clicked.connect(self.resimac)

        self.resim1 = QtWidgets.QLabel()
        layout.addWidget(self.resim1)
        self.resim1.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
        # I'm assuming the following...
        self.resim1.setScaledContents(True)
        self.resim1.setFixedSize(701,451)

        # install an event filter to "capture" mouse events (amongst others)
        self.resim1.installEventFilter(self)

    def resimac(self):
        filename, filter = QtWidgets.QFileDialog.getOpenFileName(None, 'Resim Yükle', '.', 'Image Files (*.png *.jpg *.jpeg *.bmp *.tif)')
        if not filename:
            return
        self.resim1.setPixmap(QtGui.QPixmap(filename))

    def eventFilter(self, source, event):
        # if the source is our QLabel, it has a valid pixmap, and the event is
        # a left click, proceed in trying to get the event position
        if (source == self.resim1 and source.pixmap() and not source.pixmap().isNull() and 
            event.type() == QtCore.QEvent.MouseButtonPress and
            event.button() == QtCore.Qt.LeftButton):
                self.getClickedPosition(event.pos())
        return super().eventFilter(source, event)

    def getClickedPosition(self, pos):
        # consider the widget contents margins
        contentsRect = QtCore.QRectF(self.resim1.contentsRect())
        if pos not in contentsRect:
            # outside widget margins, ignore!
            return

        # adjust the position to the contents margins
        pos -= contentsRect.topLeft()

        pixmapRect = self.resim1.pixmap().rect()
        if self.resim1.hasScaledContents():
            x = pos.x() * pixmapRect.width() / contentsRect.width()
            y = pos.y() * pixmapRect.height() / contentsRect.height()
            pos = QtCore.QPoint(x, y)
        else:
            align = self.resim1.alignment()
            # for historical reasons, QRect (which is based on integer values),
            # returns right() as (left+width-1) and bottom as (top+height-1),
            # and so their opposite functions set/moveRight and set/moveBottom
            # take that into consideration; using a QRectF can prevent that; see:
            # https://doc.qt.io/qt-5/qrect.html#right
            # https://doc.qt.io/qt-5/qrect.html#bottom
            pixmapRect = QtCore.QRectF(pixmapRect)

            # the pixmap is not left aligned, align it correctly
            if align & QtCore.Qt.AlignRight:
                pixmapRect.moveRight(contentsRect.x() + contentsRect.width())
            elif align & QtCore.Qt.AlignHCenter:
                pixmapRect.moveLeft(contentsRect.center().x() - pixmapRect.width() / 2)
            # the pixmap is not top aligned (note that the default for QLabel is
            # Qt.AlignVCenter, the vertical center)
            if align & QtCore.Qt.AlignBottom:
                pixmapRect.moveBottom(contentsRect.y() + contentsRect.height())
            elif align & QtCore.Qt.AlignVCenter:
                pixmapRect.moveTop(contentsRect.center().y() - pixmapRect.height() / 2)

            if not pos in pixmapRect:
                # outside image margins, ignore!
                return
            # translate coordinates to the image position and convert it back to
            # a QPoint, which is integer based
            pos = (pos - pixmapRect.topLeft()).toPoint()

        print('X={}, Y={}'.format(pos.x(), pos.y()))


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

This is somebody else's example code.I managed to get pixel location using the above code but how to put a dot on the clicked position on the image on every click?这是别人的示例代码。我设法使用上面的代码获得像素位置,但是如何在每次点击时在图像的点击位置上放置一个点? Also, when I click on another part of the image, I want the dot to appear on the new clicked position and be removed from the last clicked position.此外,当我单击图像的另一部分时,我希望该点出现在新的单击位置并从上次单击的位置中删除。

The logic is to store the original QPixmap, copy it, draw the point with QPainter and set it in the QLabel:逻辑是存储原始QPixmap,复制它,用QPainter绘制点并在QLabel中设置:

class Window(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)

        self.pixmap = QtGui.QPixmap()
        # ...

    def resimac(self):
        filename, filter = QtWidgets.QFileDialog.getOpenFileName(
            None, "Resim Yükle", ".", "Image Files (*.png *.jpg *.jpeg *.bmp *.tif)"
        )
        if not filename:
            return
        self.pixmap = QtGui.QPixmap(filename)
        self.resim1.setPixmap(self.pixmap.copy())

    # ...
    def getClickedPosition(self, pos):
       # ...
            pos = (pos - pixmapRect.topLeft()).toPoint()

        pixmap = self.pixmap.copy()
        painter = QtGui.QPainter(pixmap)
        painter.drawPoint(pos)
        painter.end()
        self.resim1.setPixmap(pixmap)

        print("X={}, Y={}".format(pos.x(), pos.y()))
pixmap = self.pixmap.copy()
painter = QtGui.QPainter(pixmap)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setBrush(QtGui.QColor("black"))
length = 10
rect = QtCore.QRect(0, 0, length, length)
rect.moveCenter(pos)
painter.drawEllipse(rect)
painter.end()
self.resim1.setPixmap(pixmap)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM