我有一个“有效”的例子,但有几个问题我似乎无法弄清楚。我计算了橡皮筋内的 topLeft 和 bottomRight 坐标,并将它们转换为小部件坐标。但是 pixmap.copy() 不会复制那些坐标。不断变化的全局和小部件坐标系令人困惑,所以我假设我没有正确理解坐标系。
import sys
from PyQt5.QtCore import Qt, QRect
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QRubberBand
from PyQt5.QtWidgets import QHBoxLayout, QSizeGrip
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(526, 478)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralWidget)
self.gridLayout.setContentsMargins(11, 11, 11, 11)
self.gridLayout.setSpacing(6)
self.gridLayout.setObjectName("gridLayout")
self.label = QtWidgets.QLabel(self.centralWidget)
self.label.setText("")
self.label.setPixmap(QtGui.QPixmap("ava.jpg"))
self.label.setScaledContents(True)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.pushButton = QtWidgets.QPushButton(self.centralWidget)
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 1, 0, 1, 1)
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 526, 25))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Resizeable QLabel Example"))
self.pushButton.setText(_translate("MainWindow", "Crop"))
class Test_Resize(QMainWindow, Ui_MainWindow):
def __init__(self):
super(Test_Resize, self).__init__()
self.setupUi(self)
self.show()
def run(self):
self.pushButton.clicked.connect(self.cropImage)
self.band = Resizable_rubber_band(self.label)
self.band.move(50, 50)
self.band.resize(200, 266)
self.band.setMinimumSize(30, 30)
def cropImage(self):
rect = self.band.getCoverage()
# copy(QRect( x, y, width, height))
self.label.setPixmap(self.label.pixmap().copy(rect))
self.label.repaint()
class Resizable_rubber_band(QWidget):
def __init__(self, parent=None):
super(Resizable_rubber_band, self).__init__(parent)
# tell QSizeGrip to resize this widget instead of top-level window
self.setWindowFlags(Qt.SubWindow)
self.layout = QHBoxLayout(self)
self.layout.setContentsMargins(0, 0, 0, 0)
self.grip1 = QSizeGrip(self)
self.grip2 = QSizeGrip(self)
self.layout.addWidget(self.grip1, 0, Qt.AlignLeft | Qt.AlignTop)
self.layout.addWidget(self.grip2, 0, Qt.AlignRight | Qt.AlignBottom)
self.rubberband = QRubberBand(QRubberBand.Rectangle, self)
self.rubberband.move(0, 0)
self.rubberband.show()
self.show()
def resizeEvent(self, event):
# force 4h x 3w aspect ratio using QSize
# if width < height: height = 1.333 * width
# if width > height: width = height / 1.333
# width = self.width()
# height = self.height()
# if(width < height):
# height = int(width * 1.333)
# else:
# width = int(height / 1.333)
# self.rubberband.resize(QSize(width, height))
self.rubberband.resize(self.size())
def getCoverage(self):
localCoords = self.contentsRect()
print("localCoords: ", localCoords)
TL = self.mapToGlobal(localCoords.topLeft())
BR = localCoords.bottomRight()
# TL+BR to get width & height
widgetCoords = QRect(TL, TL+BR)
print("widgetCoords: ", widgetCoords)
return widgetCoords
app = QApplication(sys.argv)
program = Test_Resize()
program.run()
sys.exit(app.exec_())
请您参考如下方法:
当您启用 scaledContents属性:
self.label.setScaledContents(True)
QPixmap 的坐标与 QLabel 的像素不对应,例如,假设 QPixmap 是 20 x 20和 QLabel 20 x 10 然后它必须在像素图的高度从 20 到 10 进行转换。
首先要做的是用self.label.mapFromGlobal()将全局坐标转换为QLabel坐标,然后通过缩放宽高来变换矩形与初始变化成正比。
def cropImage(self):
rect = self.band.getCoverage()
r = QRect(self.label.mapFromGlobal(rect.topLeft()), rect.size())
px = self.label.pixmap()
tr = QtGui.QTransform()
tr.scale(px.size().width()*1.0/self.label.size().width(), px.size().height()*1.0/self.label.size().height())
r = tr.mapRect(r)
self.label.setPixmap(px.copy(r))
