2

我有一个“工作”示例,但我似乎无法弄清楚一些问题。我已经计算了橡皮筋内的 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_())
4

1 回答 1

2

当您启用scaledContents属性时:

self.label.setScaledContents(True)

的坐标与QPixmap的像素不对应QLabel,例如,假设QPixmap是 20 x 20 和QLabel20 x 10,那么它必须在像素图的高度从 20 转换为 10。

首先要做的是将全局坐标转换为QLabel坐标self.label.mapFromGlobal(),然后通过缩放与初始变化成比例的宽度和高度来变换矩形。

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))
于 2018-01-01T22:36:03.950 回答