python - 使用可拖动的 QLabel 进行裁剪
问题描述
我正在尝试使用可拖动的 QLabels 来裁剪图像。我的代码的基本思想是分割图像中的字符。
所以,用户会先上传一张包含三个字符的图片到程序中。然后,他将通过选中合适的复选框来指定盘子的类型,是短还是长。基于复选框,将向用户显示三个具有特定大小的框(QLabels),以便他可以将每个框拖动到上传图像中的字符上。一旦用户完成将框放置在字符上,他可以单击Segment
按钮以应用裁剪操作。最终结果将是三个裁剪字符的图像。
我已经完成了程序界面和一些功能,但是,我面临着 darg 和裁剪功能的问题。我尝试过使用拖动框(QLabels)的不同方法,但它不适用于我。我真的不知道我的代码有什么问题:(。我使用的是python 3和PyQt5。
这是我的代码:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QLabel, QWidget
from PyQt5.QtGui import QDrag, QPixmap, QPainter, QCursor
from PyQt5.QtCore import QMimeData, Qt
boxes_items = []
#=========================================================================
class DraggableLabel(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
event.accept()
event.acceptProposedAction()
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
event.accept()
self.setCursor(QtGui.QCursor(QtCore.Qt.CloseHandCursor))
self.drag_start_position = event.pos()
def mouseMoveEvent(self, event):
if not (event.buttons() & Qt.LeftButton):
return
if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
return
drag = QDrag(self)
'''
mimedata = QMimeData()
#mimedata.setText(self.text())
mimedata.setImageData(self.pixmap().toImage())
drag.setMimeData(mimedata)
pixmap = QPixmap(self.size())
painter = QPainter(pixmap)
painter.drawPixmap(self.rect(), self.grab())
painter.end()
drag.setPixmap(pixmap)
'''
drag.setHotSpot(event.pos())
drag.exec_(Qt.CopyAction | Qt.MoveAction)
'''
class DropLabel(QLabel):
def __init__(self, *args, **kwargs):
QLabel.__init__(self, *args, **kwargs)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if event.mimeData().hasText():
event.acceptProposedAction()
def dropEvent(self, event):
pos = event.pos()
self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
# text = event.mimeData().text()
# self.setText(text)
event.acceptProposedAction()
'''
#==========================================================================
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setEnabled(True)
Dialog.resize(1050, 800)
Dialog.setMinimumSize(QtCore.QSize(1050, 800))
Dialog.setMaximumSize(QtCore.QSize(1050, 800))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("../.designer/backup/project pic/images LPR icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Dialog.setWindowIcon(icon)
Dialog.setStyleSheet("background-color: rgb(217, 217, 217);\n"
"background-color: rgb(243, 243, 243);")
# Dialog.setAcceptDrops(True)
self.BrowesImageButton = QtWidgets.QPushButton(Dialog)
self.BrowesImageButton.setGeometry(QtCore.QRect(820, 60, 200, 60))
self.BrowesImageButton.setMinimumSize(QtCore.QSize(200, 60))
self.BrowesImageButton.setMaximumSize(QtCore.QSize(200, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.BrowesImageButton.setFont(font)
self.BrowesImageButton.setStyleSheet("")
self.BrowesImageButton.setCheckable(True)
self.BrowesImageButton.setObjectName("BrowesImageButton")
self.groupBox = QtWidgets.QGroupBox(Dialog)
self.groupBox.setGeometry(QtCore.QRect(820, 170, 211, 131))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.groupBox.setFont(font)
self.groupBox.setLayoutDirection(QtCore.Qt.LeftToRight)
self.groupBox.setObjectName("groupBox")
self.checkBox_Short = QtWidgets.QCheckBox(self.groupBox)
self.checkBox_Short.setGeometry(QtCore.QRect(20, 40, 141, 23))
font = QtGui.QFont()
font.setFamily("Adobe Heiti Std R")
font.setPointSize(10)
self.checkBox_Short.setFont(font)
self.checkBox_Short.setLayoutDirection(QtCore.Qt.LeftToRight)
self.checkBox_Short.setObjectName("checkBox_Short")
self.checkBox_Short.setEnabled(False)
self.checkBox_Long = QtWidgets.QCheckBox(self.groupBox)
self.checkBox_Long.setGeometry(QtCore.QRect(20, 80, 141, 23))
font = QtGui.QFont()
font.setFamily("Adobe Heiti Std R")
font.setPointSize(10)
self.checkBox_Long.setFont(font)
self.checkBox_Long.setLayoutDirection(QtCore.Qt.LeftToRight)
self.checkBox_Long.setObjectName("checkBox_Long")
self.checkBox_Long.setEnabled(False)
self.SegmentImageButton = QtWidgets.QPushButton(Dialog)
self.SegmentImageButton.setGeometry(QtCore.QRect(830, 330, 200, 60))
self.SegmentImageButton.setMinimumSize(QtCore.QSize(200, 60))
self.SegmentImageButton.setMaximumSize(QtCore.QSize(200, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.SegmentImageButton.setFont(font)
self.SegmentImageButton.setStyleSheet("")
self.SegmentImageButton.setCheckable(True)
self.SegmentImageButton.setObjectName("SegmentImageButton")
self.SegmentImageButton.setEnabled(False)
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(980, 470, 45, 45))
self.label.setMinimumSize(QtCore.QSize(45, 45))
self.label.setMaximumSize(QtCore.QSize(45, 45))
self.label.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self.label.setMouseTracking(True)
self.label.setAcceptDrops(True)
self.label.setStyleSheet("border-color: rgb(238, 0, 0); border-width : 2.0px; border-style:inset;")
self.label.setFrameShape(QtWidgets.QFrame.Box)
self.label.setLineWidth(2)
self.label.setText("")
self.label.setObjectName("label")
self.label.hide()
'''
self.graphicsView = QtWidgets.QGraphicsView(Dialog)
self.graphicsView.setGeometry(QtCore.QRect(40, 40, 750, 500))
self.graphicsView.setMinimumSize(QtCore.QSize(750, 500))
self.graphicsView.setMaximumSize(QtCore.QSize(750, 500))
self.graphicsView.setObjectName("graphicsView")
'''
self.UserImageLbl = QtWidgets.QLabel(Dialog)
self.UserImageLbl.setGeometry(QtCore.QRect(40, 40, 750, 500))
self.UserImageLbl.setMinimumSize(QtCore.QSize(750, 500))
self.UserImageLbl.setMaximumSize(QtCore.QSize(750, 500))
self.UserImageLbl.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.UserImageLbl.setFrameShadow(QtWidgets.QFrame.Plain)
self.UserImageLbl.setLineWidth(1)
self.UserImageLbl.setMidLineWidth(0)
self.UserImageLbl.setText("")
self.UserImageLbl.setScaledContents(False)
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter)
self.UserImageLbl.setObjectName("UserImageLbl")
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setGeometry(QtCore.QRect(900, 470, 45, 45))
self.label_2.setMinimumSize(QtCore.QSize(45, 45))
self.label_2.setMaximumSize(QtCore.QSize(45, 45))
self.label_2.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self.label_2.setMouseTracking(True)
self.label_2.setAcceptDrops(True)
self.label_2.setStyleSheet("border-color: rgb(238, 0, 0); border-width : 2.0px; border-style:inset;")
self.label_2.setFrameShape(QtWidgets.QFrame.Box)
self.label_2.setLineWidth(2)
self.label_2.setText("")
self.label_2.setObjectName("label_2")
self.label_2.hide()
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setGeometry(QtCore.QRect(820, 470, 45, 45))
self.label_3.setMinimumSize(QtCore.QSize(45, 45))
self.label_3.setMaximumSize(QtCore.QSize(45, 45))
self.label_3.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self.label_3.setMouseTracking(True)
self.label_3.setAcceptDrops(True)
self.label_3.setStyleSheet("border-color: rgb(238, 0, 0); border-width : 2.0px; border-style:inset;")
self.label_3.setFrameShape(QtWidgets.QFrame.Box)
self.label_3.setLineWidth(2)
self.label_3.setText("")
self.label_3.setObjectName("label_3")
self.label_3.hide()
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
#Add labels in boxes items list
boxes_items.append(self.label)
boxes_items.append(self.label_2)
boxes_items.append(self.label_3)
#=================================== Calling =======================
self.BrowesImageButton.clicked.connect(self.setImage)
self.checkBox_Short.stateChanged.connect(self.Change_the_Checkbox_Short_Function)
self.checkBox_Long.stateChanged.connect(self.Change_the_Checkbox_Long_Function)
#=================================== Functions =========================
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Cropping"))
self.BrowesImageButton.setText(_translate("Dialog", "Select Image"))
self.groupBox.setTitle(_translate("Dialog", "Choose Plate Type"))
self.checkBox_Short.setText(_translate("Dialog", "Short Plate"))
self.checkBox_Long.setText(_translate("Dialog", "Long Plate"))
self.SegmentImageButton.setText(_translate("Dialog", "Segment Image"))
self.label.setToolTip(_translate("Dialog", "Drage it on first charecter"))
self.label_2.setToolTip(_translate("Dialog", "Drage it on second charecter"))
self.label_3.setToolTip(_translate("Dialog", "Drage it on third charecter"))
#=================================================================================
def setImage(self):
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Image", "", "Image Files (*.png *.jpg *jpeg *.bmp)") # Ask for file
if fileName: # If the user gives a file
pixmap = QtGui.QPixmap(fileName) # Setup pixmap with the provided image
pixmap = pixmap.scaled(self.UserImageLbl.width(), self.UserImageLbl.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
self.UserImageLbl.setPixmap(pixmap) # Set the pixmap onto the label
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter) # Align the label to center
#UserImageLbl = DropLabel()
self.checkBox_Short.setEnabled(True)
self.checkBox_Long.setEnabled(True)
#=====================================================================
def Change_the_Checkbox_Short_Function(self):
if self.checkBox_Short.isChecked():
self.checkBox_Long.setEnabled(False)
self.SegmentImageButton.setEnabled(True)
# Presenting 3 boxes 45x45 hear
for box_item in boxes_items:
#box_item.setDragEnabled(True)
box_item.setMinimumSize(QtCore.QSize(45, 45))
box_item.setMaximumSize(QtCore.QSize(45, 45))
box_item.show()
box_item = DraggableLabel()
else:
self.checkBox_Long.setEnabled(True)
for box_item in boxes_items:
box_item.hide()
#========================================================================
def Change_the_Checkbox_Long_Function(self):
if self.checkBox_Long.isChecked():
self.checkBox_Short.setEnabled(False)
self.SegmentImageButton.setEnabled(True)
# Presenting 3 boxes 40x40 hear
for box_item in boxes_items:
# box_item.setDragEnabled(True)
box_item.setMinimumSize(QtCore.QSize(40, 40))
box_item.setMaximumSize(QtCore.QSize(40, 40))
box_item.show()
box_item = DraggableLabel()
#for box_item in Sboxes_items:
#DraggableLabel(box_item)
else:
self.checkBox_Short.setEnabled(True)
for box_item in boxes_items:
box_item.hide()
#==========================================================================
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
我希望我能找到可以帮助我的人。提前致谢。
解决方案
我相信您对拖放的工作原理有些困惑,但最重要的是,您不需要“实际的”拖放来实现您想要实现的目标。
在这个例子中,我添加了可拖动的框而不是标签,它们可以在图像矩形内自由移动。我不得不对您的原始代码进行一些修改,因为它有点令人困惑并且有一些根本不起作用的逻辑。
class DraggableLabel(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setStyleSheet("border-color: rgb(238, 0, 0); border-width : 2.0px; border-style:inset; background: transparent;")
self.origin = None
def setLimits(self, rect):
self.limits = rect
def mousePressEvent(self, event):
if not self.origin:
# update the origin point, we'll need that later
self.origin = self.pos()
if event.button() == Qt.LeftButton:
self.mousePos = event.pos()
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton:
# move the box
self.move(self.pos() + event.pos() - self.mousePos)
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
# if the box is not within the image boundaries, move it
# back to the original position
if not self.limits.contains(self.geometry()):
self.move(self.origin)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setEnabled(True)
Dialog.resize(1050, 800)
Dialog.setMinimumSize(QtCore.QSize(1050, 800))
Dialog.setMaximumSize(QtCore.QSize(1050, 800))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("../.designer/backup/project pic/images LPR icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Dialog.setWindowIcon(icon)
Dialog.setStyleSheet("background-color: rgb(217, 217, 217);\n"
"background-color: rgb(243, 243, 243);")
# Dialog.setAcceptDrops(True)
self.BrowesImageButton = QtWidgets.QPushButton(Dialog)
self.BrowesImageButton.setGeometry(QtCore.QRect(820, 60, 200, 60))
self.BrowesImageButton.setMinimumSize(QtCore.QSize(200, 60))
self.BrowesImageButton.setMaximumSize(QtCore.QSize(200, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.BrowesImageButton.setFont(font)
self.BrowesImageButton.setStyleSheet("")
self.BrowesImageButton.setCheckable(True)
self.BrowesImageButton.setObjectName("BrowesImageButton")
self.groupBox = QtWidgets.QGroupBox(Dialog)
self.groupBox.setGeometry(QtCore.QRect(820, 170, 211, 131))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.groupBox.setFont(font)
self.groupBox.setLayoutDirection(QtCore.Qt.LeftToRight)
self.groupBox.setObjectName("groupBox")
self.checkBox_Short = QtWidgets.QCheckBox(self.groupBox)
self.checkBox_Short.setGeometry(QtCore.QRect(20, 40, 141, 23))
font = QtGui.QFont()
font.setFamily("Adobe Heiti Std R")
font.setPointSize(10)
self.checkBox_Short.setFont(font)
self.checkBox_Short.setLayoutDirection(QtCore.Qt.LeftToRight)
self.checkBox_Short.setObjectName("checkBox_Short")
self.checkBox_Short.setEnabled(False)
self.checkBox_Long = QtWidgets.QCheckBox(self.groupBox)
self.checkBox_Long.setGeometry(QtCore.QRect(20, 80, 141, 23))
font = QtGui.QFont()
font.setFamily("Adobe Heiti Std R")
font.setPointSize(10)
self.checkBox_Long.setFont(font)
self.checkBox_Long.setLayoutDirection(QtCore.Qt.LeftToRight)
self.checkBox_Long.setObjectName("checkBox_Long")
self.checkBox_Long.setEnabled(False)
self.SegmentImageButton = QtWidgets.QPushButton(Dialog)
self.SegmentImageButton.setGeometry(QtCore.QRect(830, 330, 200, 60))
self.SegmentImageButton.setMinimumSize(QtCore.QSize(200, 60))
self.SegmentImageButton.setMaximumSize(QtCore.QSize(200, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.SegmentImageButton.setFont(font)
self.SegmentImageButton.setStyleSheet("")
self.SegmentImageButton.setCheckable(True)
self.SegmentImageButton.setObjectName("SegmentImageButton")
self.SegmentImageButton.setEnabled(False)
self.UserImageLbl = QtWidgets.QLabel(Dialog)
self.UserImageLbl.setGeometry(QtCore.QRect(40, 40, 750, 500))
self.UserImageLbl.setMinimumSize(QtCore.QSize(750, 500))
self.UserImageLbl.setMaximumSize(QtCore.QSize(750, 500))
self.UserImageLbl.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.UserImageLbl.setFrameShadow(QtWidgets.QFrame.Plain)
self.UserImageLbl.setLineWidth(1)
self.UserImageLbl.setMidLineWidth(0)
self.UserImageLbl.setText("")
self.UserImageLbl.setScaledContents(False)
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter)
self.UserImageLbl.setObjectName("UserImageLbl")
self.buttonGroup = QButtonGroup()
self.buttonGroup.addButton(self.checkBox_Short)
self.buttonGroup.addButton(self.checkBox_Long)
self.label_1 = DraggableLabel(Dialog)
self.label_2 = DraggableLabel(Dialog)
self.label_3 = DraggableLabel(Dialog)
self.label_1.move(820, 470)
self.label_2.move(900, 470)
self.label_3.move(980, 470)
self.labels = [self.label_1, self.label_2, self.label_3]
for label in self.labels:
label.hide()
label.raise_()
self.BrowesImageButton.clicked.connect(self.setImage)
self.checkBox_Long.toggled.connect(self.setBoxSizes)
self.checkBox_Short.toggled.connect(self.setBoxSizes)
def setImage(self):
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Image", "", "Image Files (*.png *.jpg *jpeg *.bmp)") # Ask for file
if fileName: # If the user gives a file
pixmap = QtGui.QPixmap(fileName) # Setup pixmap with the provided image
pixmap = pixmap.scaled(self.UserImageLbl.width(), self.UserImageLbl.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
self.UserImageLbl.setPixmap(pixmap) # Set the pixmap onto the label
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter) # Align the label to center
#UserImageLbl = DropLabel()
self.checkBox_Short.setEnabled(True)
self.checkBox_Long.setEnabled(True)
def setBoxSizes(self):
if self.checkBox_Short.isChecked():
boxSize = 40
else:
boxSize = 45
for label in self.labels:
label.setFixedSize(boxSize, boxSize)
label.setLimits(self.UserImageLbl.geometry())
label.show()
推荐阅读
- javascript - 在任何给定时间突出显示列表中的一项(默认为索引 0)
- azure-devops - 发布管道中缺少“启用系统诊断”
- mysql - 如何使用sql查询获取依赖数据
- ios - 非'@objc' 方法不满足'@objc' 协议的要求
- c# - 将 Property Attributes 的 TypeOf 值标识为现有类名
- ios - UIView 动画选项重复计数
- wordpress - 为什么 WordPress 为我的单作者页面创建分页?
- c - “llvm/libexec/clang-cc”有什么作用?
- node.js - 为什么 sequelize-cli 不在模型文件中包含 ID?
- playframework - 如何使用 Play 1.2.5 与 Mavan 同步