python pyqt5学习笔记 2020.9.29(改变鼠标样式,获取鼠标当前位置坐标,鼠标控制qlabel图片移动和图片的缩放)

改变鼠标的样式

python pyqt5学习笔记 2020.9.29(改变鼠标样式,获取鼠标当前位置坐标,鼠标控制qlabel图片移动和图片的缩放)_第1张图片
表格来自:https://blog.csdn.net/qq_38783863/article/details/103951314

使用时:

#鼠标移入label1中变成普通光标
self.ui.label1.setCursor(QtCore .Qt.PointingHandCursor)       #手型光标

鼠标相关事件

python pyqt5学习笔记 2020.9.29(改变鼠标样式,获取鼠标当前位置坐标,鼠标控制qlabel图片移动和图片的缩放)_第2张图片
表格来自: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()

pyqt5 拖拽Qlabel中的图片移动

找了很久没有找到移动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 = ""

pyqt5 滚轮控制图片的大小

简单来说就是通过滚轮滚动事件来控制图片和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)

运行结果:

python pyqt5学习笔记 2020.9.29(改变鼠标样式,获取鼠标当前位置坐标,鼠标控制qlabel图片移动和图片的缩放)_第3张图片

你可能感兴趣的:(python,qt)