我正在使用PyQt中的网络摄像头制作图像采集程序。每当我单击标签窗口小部件内的图像时,我都需要在该位置放置一个额外的固定光标(例如,有一个参考点)。我创建了一个游标对象,设置了形状和位置(从单击的位置获得)。但我看不到在单击位置即Qpoint
处创建的其他光标下面是代码段:
def eventFilter(self, source, event):
if event.type()==QtCore.QEvent.MouseButtonPress:
self.new_cursor=QtGui.QCursor() # the additional cursori want to place
self.new_cursor.setShape(self,Qt.PointingHandCursor) # setting shape
self.cursor_clicked=event.pos() # getting position from the click
self.cursor_clicked=self.label.mapFromParent(event.pos()) #mapping to widget coords.
self.cursor_x=self.cursor_clicked.x()
self.cursor_y=self.cursor_clicked.y()
self.new_cursor.setPos(self.cursor_x,self.cursor_y)
self.setCursor(self.new_cursor)
return QtWidgets.QWidget.eventFilter(self,source,event)
答案 0 :(得分:1)
QCursor不是“静态图像”,而是与鼠标光标有关的“抽象”对象,因此没有出于您的目的使用它。
您要查找的是在现有图像或显示该图像的小部件上进行绘制。
由于您可能想保持图像不变,因此第二个选择就是您要寻找的东西。
这个想法是,您调用paintEvent
方法的基类实现,然后在其上绘制。。
使用简单的线条手工绘制十字准线并不难,但是您需要使用不同的颜色在十字周围画一个额外的边框,以确保即使在较亮或较暗的背景下,它的可见性也是如此。在此示例中,我使用的是CursorShape enum文档中Qt使用的光标图像,但是只要其中心正好位于它的 the 中心,您就可以使用所需的任何图像(提示:请使用宽度/高度为奇数的正方形图像。
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QGridLayout(self)
self.label = QtWidgets.QLabel()
layout.addWidget(self.label)
self.label.setPixmap(QtGui.QPixmap('myimage.png'))
self.label.installEventFilter(self)
self.cursorPos = None
# I'm using the crosshair cursor as shown at
# https://doc.qt.io/qt-5/qt.html#CursorShape-enum
self.cursorPixmap = QtGui.QPixmap('cursor-cross.png')
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.MouseButtonPress:
# set the current position and schedule a repaint of the label
self.cursorPos = event.pos()
self.label.update()
elif event.type() == QtCore.QEvent.Paint:
# intercept the paintEvent of the label and call the base
# implementation to actually draw its contents
self.label.paintEvent(event)
if self.cursorPos is not None:
# if the cursor position has been set, draw it
qp = QtGui.QPainter(self.label)
# translate the painter at the cursor position
qp.translate(self.cursorPos)
# paint the pixmap at an offset based on its center
qp.drawPixmap(-self.cursorPixmap.rect().center(), self.cursorPixmap)
return True
return super().eventFilter(source, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
除此之外,另一种方法是使用Graphics View Framework,将像素图添加到场景中,并在用户单击图像时为光标添加/移动另一个像素图。处理QGraphicsViews,QGraphicsScenes及其项目要复杂一些,但是如果您需要与图像进行更高级的交互,通常是更好的选择。
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QGridLayout(self)
self.view = QtWidgets.QGraphicsView()
layout.addWidget(self.view)
# remove any border around the view
self.view.setFrameShape(0)
self.scene = QtWidgets.QGraphicsScene()
self.view.setScene(self.scene)
pixmap = QtGui.QPixmap('myimage.png')
# adapt the view's size to that of the pixmap
self.view.setFixedSize(pixmap.size())
# add a pixmap to a scene, which returns a QGraphicsPixmapItem
self.pixmapItem = self.scene.addPixmap(pixmap)
self.crossHairItem = None
self.view.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.MouseButtonPress:
if not self.crossHairItem:
# as above, get a QGraphicsPixmapItem for the crosshair cursor
pixmap = QtGui.QPixmap('cursor-cross.png')
self.crossHairItem = self.scene.addPixmap(pixmap)
# set an offset of the item, so that its position is always
# based on the center of the pixmap
self.crossHairItem.setOffset(-pixmap.rect().center())
self.crossHairItem.setPos(self.view.mapToScene(event.pos()))
return super().eventFilter(source, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
这两种方法对用户的行为都相同,如您所见,它们看起来完全相同。