作为菜鸟为了实现这两个功能,肯定是要借鉴一下大佬的文章的,下面的链接就是我思路的源头:
https://blog.csdn.net/qq_36780295/article/details/108844005
这个大佬的几篇文章详细介绍了关于图片的拖拽,但是关于图片的缩放这位大佬已经实现但并未具体讲述,甚至会产生一些误导(当然可能是这位大佬未注意吧),我也是迷了到好久才走出来,下面便开始介绍自己的思路。
首先关于label标签内插入图片,为了实现图片的移动,可以将label标签插入到一个容器内,我选择的是QGroupBox,设置窗口的代码如下:
class Ui_Form(QtWidgets.QWidget):
def __init__(self):
super(Ui_Form, self).__init__()
self.setGeometry(100,100,1000,800)
self.setWindowTitle('image')
self.groupBox = QtWidgets.QGroupBox(self) #设置的groupBox容器
self.groupBox.setGeometry(QtCore.QRect(10, 60, 841, 611))
self.groupBox.setObjectName("groupBox")
self.label = QtWidgets.QLabel(self.groupBox) #设置的位于容器内部的label控件
self.label.setCursor(QtCore.Qt.PointingHandCursor)
self.label.setGeometry(QtCore.QRect(0, 0, 621, 461))
self.label.setObjectName("label")
self.label.setAlignment(QtCore.Qt.AlignCenter)
关于图片的插入我这里是设置了一个按钮控件链接到一个槽函数获取本地图片文件,然后显示在label上:
def on_pushButton1_clicked(self):
self.path = QtWidgets.QFileDialog.getOpenFileName()#获取本地文件路径
self.cur_img = cv.imread(self.path[0]) #此处使用了OpenCV包的函数
self.img = QPixmap(self.path[0]) #获取QPimax对象
self.label.setPixmap(self.img) #插入label中
self.label.setFrameShape(QtWidgets.QFrame.Box) #设置label标签的边框
self.label.setLineWidth(1)
self.label_w = self.label.width()
self.label_x = self.label.x()
self.label_y = self.label.y()
self.label_h = self.label.height()
self.label.setScaledContents(True) #设置label内部图片自适应填充
随后便是实现图片的拖拽了,这里我们需要实现鼠标按下、释放以及鼠标移动事件:
def mousePressEvent(self, e):
if e.buttons() == QtCore.Qt.LeftButton:
self.flag = True
def mouseReleaseEvent(self, e): #鼠标释放事件重写
self.flag = False
self.movex = ""
self.movey = ""
这里设置的中间点需要我们在之前设置好,这里每次释放的时候把其全部清空,然后便是鼠标移动事件
def mouseMoveEvent(self, e):
if self.flag:
self.x1 = e.x()
self.y1 = e.y()
if self.movex != "" and self.movey != "":
self.label_x = self.label_x + (self.x1 - self.movex)
self.label_y = self.label_y + (self.y1 - self.movey)
self.movex = self.x1
self.movey = self.y1
self.label.setGeometry(QtCore.QRect(self.label_x, self.label_y, self.label_w, self.label_h)) #使得图片能够随着缩放而不影响大小,
#同时QtCore.QRect确定图形为矩形
显然,拖拽事件是利用鼠标按下时flag为True,结合鼠标移动事件在释放时重新获得label标签的坐标,鼠标释放时将中间点清空,以防止影响下一次拖拽事件。这里需要细品的就是鼠标移动事件里的第二个if语句的内容,通过判断中间点的坐标是否为空来进行事件的进行。
在说思路之前我们先看一张图:(这个图只是作为一个参考,白色为label区域,蓝色为QgroudBox)
这样我们就能够得到鼠标在窗口里相对于label的具体坐标,因为我们要实现的是根据鼠标为中心进行缩放,第一次鼠标坐标与label宽、高的比值,和第二次鼠标坐标(相对于label)和label宽高的比值是相等的,通过计算那么我们就能得到第二次进行缩放之后label标签的坐标,这样我们就能够将新的label显示出来。
def wheelEvent(self,e):
self.angle = e.angleDelta()/8
self.angleY = self.angle.y()
if self.angleY > 0:
if self.resize_point >=1 and self.resize_point <=19 : #此处的self.resize_point初始值为10,作为缩放系数
self.resize_point +=1
elif self.angleY < 0:
if self.resize_point >=2 and self.resize_point <=20:
self.resize_point -=1
x_1 = e.x()
y_1 = e.y()
x2 = (x_1 - 10- self.label.x())/self.label.width() #第一次鼠标坐标x比值
y2 = (y_1 - 60- self.label.y())/self.label.height() #第一次鼠标坐标y比值
#由于cV2包得到图像并非是我们所需的图片对象,这里先是对图片宽高根据缩放系数进行改变,然后将图片转换为QImage对象,在转换为QPixmap对象
self.cur_resimg = cv.resize(self.cur_img,((int(self.cur_img.shape[1]*self.resize_point/10)),(int(self.cur_img.shape[0]*self.resize_point/10))))
img2 = cv.cvtColor(self.cur_resimg, cv.COLOR_BGR2RGB) #转RGB格式,以在Qlabel中显示
QImage = QtGui.QImage(img2, self.cur_resimg.shape[1], self.cur_resimg.shape[0], 3 * self.cur_resimg.shape[1],
QtGui.QImage.Format_RGB888)
pixmap = QtGui.QPixmap((QImage).scaled(self.cur_resimg.shape[1], self.cur_resimg.shape[0]))
self.label_w = self.cur_resimg.shape[1]
self.label_h = self.cur_resimg.shape[0]
if int(x2)==0 and int(y2)==0 :
x3 = x2
y3 = y2
Lmx2 = x3 * self.label_w
Lmy2 = y3 * self.label_h
self.label_x = int(x_1 - 10 - Lmx2)
self.label_y = int(y_1 - 60 - Lmy2)
self.label.setGeometry(QtCore.QRect(self.label_x,self.label_y,self.label_w,self.label_h))
self.label.setPixmap(pixmap)
以上代码就实现了关于图片的滑动。
2021.07.07
资源如下:
https://download.csdn.net/download/zhaodongdz/20588516