表格来自:https://blog.csdn.net/qq_38783863/article/details/103951314
使用时:
#鼠标移入label1中变成普通光标
self.ui.label1.setCursor(QtCore .Qt.PointingHandCursor) #手型光标
表格来自:https://blog.csdn.net/qq_38783863/article/details/103951314
鼠标滚轮事件:
def wheelEvent(self, event):
#self.angle的输出结果为:
#向前滚:PyQt5.QtCore.QPoint(0, 15),angle.y()=15
#向后滚:PyQt5.QtCore.QPoint(0, -15),angle.y()=-15
self.angle = event.angleDelta( ) /8
self.y = self.angle.y()
import pyautogui as pag
while True:
print(pag.position()[0],pag.position()[1])
#或者
import pyautogui as pag
x,y = pag.position()
找了很久没有找到移动label中图片的方法,在网上看到大佬的留言,找到了方法。
设置一个容器来容纳这个label,把移动图片改为移动Qlabel。
比如我像下面这样设置:
#图片显示区域容器
self.pic_box = QtWidgets.QGroupBox(self.label_frame)
self.pic_box.setGeometry(QtCore.QRect(5,5,1536,864))
self.pic_box.setStyleSheet("border: 1px solid grey")
#图片显示区域
self.lflabel1 = QtWidgets.QLabel(self.pic_box)
self.lflabel1.setGeometry(QtCore.QRect(-200,-200,1536,864))
self.lflabel1.setStyleSheet("border: 1px solid grey")
self.lflabel1.setAlignment(QtCore.Qt.AlignCenter)
这样就出现了一种图片移动了的错觉:
为了完善这一功能,我设置了两个全局变量,指向上一次鼠标点击移动的坐标:
#鼠标移动坐标指针
self.mouse_mv_x = ""
self.mouse_mv_y = ""
接着来写鼠标移动事件:
#鼠标点击时 flag = true,判断移动
def mouseMoveEvent(self,event):
if self.flag: #鼠标被点击信号,为True表示鼠标点击事件触发
self.x1 = event.x()
self.y1 = event.y()
if self.mouse_mv_x != "": #self.mouse_mv_x的初始值为""
if self.mouse_mv_y != "":
self.labelx = self.labelx + (self.x1 - self.mouse_mv_x)
self.labely = self.labely + (self.y1 - self.mouse_mv_y)
self.mouse_mv_x = self.x1 #记录拖拽时上一个点的坐标
self.mouse_mv_y = self.y1
self.ui.lflabel1.setGeometry(QtCore.QRect(self.labelx,self.labely,self.label_wid,self.label_hig))
还有在鼠标释放时,一定要将两个记录上次坐标的指针初始化:
#鼠标释放事件
def mouseReleaseEvent(self,event):
self.flag = False
#销毁结点指针
self.mouse_mv_y = ""
self.mouse_mv_x = ""
简单来说就是通过滚轮滚动事件来控制图片和label的大小,与之前鼠标拖拽图片移动不同的是之前控制的是label的初始坐标。
#初始化时,设置一个放缩系数
self.resize_point = 10
#滚轮滑动事件
def wheelEvent(self, event):
if self.ui.stacked.currentIndex() == 1: #是否图片标注按钮页
if self.curr_pic != "": #图片是否加载
if pag.position()[0]>5 and pag.position()[0]<3+self.ui.pic_box.width(): #鼠标在label的显示图片区域内 #光标当前坐标 x
if pag.position()[1]>105 and pag.position()[1]<105+self.ui.pic_box.height(): #光标当前坐标y
self.angle = event.angleDelta( ) /8 #滚轮滚动的角度
self.angleY = self.angle.y() #+-15
if self.angleY>0: # 15向上滚动
if self.resize_point>0 and self.resize_point<20: #放大上下限
self.resize_point += 1 #向上滚动,放缩系数+1
if self.angleY<0: # -15向下滚动
if self.resize_point>1 and self.resize_point<21: #缩小上下限
self.resize_point -= 1 #向下滚动,放缩系数-1
self.cur_resimg = cv2.resize(self.cur_img,(int(self.cur_lab_shape[1]*self.resize_point/10),int(self.cur_lab_shape[0]*self.resize_point/10))) #图片按10%作为比例进行放缩
self.cur_reslab_shape = self.cur_resimg.shape
img2 = cv2.cvtColor(self.cur_resimg, cv2.COLOR_BGR2RGB) #转RGB格式,以在Qlabel中显示
QImage = QtGui.QImage(img2, self.cur_reslab_shape[1], self.cur_reslab_shape[0],3*self.cur_reslab_shape[1],QtGui.QImage.Format_RGB888)
pixmap = QtGui.QPixmap(QImage).scaled(self.cur_reslab_shape[1],self.cur_reslab_shape[0])
self.label_wid = self.cur_reslab_shape[1] #label宽度指针
self.label_hig = self.cur_reslab_shape[0] #label高度指针
self.ui.lflabel1.setGeometry(QtCore.QRect(self.labelx,self.labely,self.label_wid,self.label_hig))
self.ui.lflabel1.setPixmap(pixmap)
self.has_been_chgd = True #图片缩放指针,代表图片被缩放(由于打开文件夹和切换文件夹中图片时,显示图片是自适应的,缩放是按原图进行缩放的,所以必须区别对待)
同样的,完成工作的全局变量需要在下一张图片被读取时进行初始化。
运行结果:
图片的拖动和缩放等都通过光标实现,为了与画笔和橡皮擦区分,我又加了个元件信号:
self.element_flag = "pen" #控件指针指向画笔
self.element_flag = "mouse" #控件指针指向光标
self.element_flag = "rubber" #空间指针指向橡皮擦
一定要注意的是这些全局变量在图片传入的接口中必须初始化,否则还会调用上一次结束时的结果。
在这里写了个简易的涂画+移动图片+滚动缩放的案例,以供参考:https://blog.csdn.net/qq_36780295/article/details/109034448
关于如何实现qlabel
图片根据鼠标指针的位置进行放大和缩小,我写在了:https://blog.csdn.net/qq_36780295/article/details/113696987 挺困难的,里面可能写的有点乱,希望能够有帮助吧。
以上操作都完成以后就很简单了,只需要在鼠标点击信号+鼠标移动事件中,获取鼠标的坐标,先减去移动的像素数,再将结果除以放缩倍数,就得到了原图上的坐标,然后再将这个坐标在画布上进行画图就行了。
实现代码:
elif self.has_been_chgd == True or self.has_been_mvd == True: #执行过缩放或者拖拽时执行以下代码
if self.x1>5 + self.labelx and self.x1<5 + + self.labelx + self.label_wid: #鼠标移动范围在label的显示图片区域内
if self.y1>105 + self.labely and self.y1<105 + self.labely + self.label_hig:
if self.draw_board != "": #画布已完成初始化
mv_x = self.x1 - 5 - self.labelx #减去拖拽指针坐标
mv_y = self.y1 - 105 - self.labely
chg_x = mv_x / self.resize_point*10 #除以缩放倍率
chg_y = mv_y / self.resize_point*10
cv2.circle(self.cur_img, (int(chg_x), int(chg_y)), self.radius*self.pen_times, self.pen_color(), -1) #画圆
cv2.circle(self.draw_board, (int(chg_x), int(chg_y)), self.radius*self.pen_times, self.pen_color(), -1)
if self.start_point != "": #是否为第二个点
cv2.line(self.cur_img, self.start_point, (int(chg_x), int(chg_y)), self.pen_color(), 2*self.pen_times*self.radius, 4) #画直线
cv2.line(self.draw_board, self.start_point, (int(chg_x), int(chg_y)), self.pen_color(), 2*self.pen_times*self.radius, 4)
#存储点坐标
self.start_point = (int(chg_x), int(chg_y))
img2 = cv2.cvtColor(self.cur_img, cv2.COLOR_BGR2RGB)
QImage = QtGui.QImage(img2, self.cur_lab_shape[1], self.cur_lab_shape[0],3*self.cur_lab_shape[1],QtGui.QImage.Format_RGB888)
pixmap = QtGui.QPixmap(QImage).scaled(self.ui.lflabel1.width(),self.ui.lflabel1.height())
self.ui.lflabel1.setPixmap(pixmap)