在Qlab中获取QPixmap的实际大小

2024-09-27 18:24:46 发布

您现在位置:Python中文网/ 问答频道 /正文

在PyQt5中有没有一些简单的方法来获取QLabel中显示的pixmap的真实维度?我试着用橡皮筋选择图像的一部分。但我找不到一个方法来限制橡皮筋只限于pixmap。这个QLabel.pixmap标签().rect()返回整个QLabel的维度,而不仅仅是pixmap。当pixmap被缩放并且图片的侧面有条纹时,问题就出现了。在

示例图像

示例图像2

我贴的都是不言而喻的。我不想让橡皮筋从照片中移到白色条纹上。在

class ResizableRubberBand(QWidget):

    def __init__(self, parent=None):
        super(ResizableRubberBand, self).__init__(parent)

        self.aspect_ratio = None

        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.setStyle(QStyleFactory.create("Fusion"))
        self.rubberband.move(0, 0)
        self.rubberband.show()
        self.show()


class ResizablePixmap(QLabel):

    def __init__(self, bytes_image):

        QLabel.__init__(self)
        self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.setAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
        self.setStyleSheet("background-color:#ffffff;")

        self.update_pixmap(bytes_image)

    def resizeEvent(self, event):

        if event:
            x = event.size().width()
            y = event.size().height()
        else:
            x = self.width()
            y = self.height()

        self.current_pixmap = self._bytes2pixmap(self.bytes_image_edit)
        self.setPixmap(self.current_pixmap.scaled(x, y, Qt.KeepAspectRatio))
        self.resize(x, y)

    def update_pixmap(self, bytes_image):

        self.bytes_image_edit = bytes_image

        self.current_pixmap = self._bytes2pixmap(bytes_image)
        self.setPixmap(self.current_pixmap)

        self.resizeEvent(None)

    @staticmethod
    def _bytes2pixmap(raw_image):

        image = QImage()
        image.loadFromData(raw_image)
        return QPixmap(image)

    @staticmethod
    def _pixmap2bytes(pixmap):

        byte_array = QByteArray()
        buffer = QBuffer(byte_array)
        buffer.open(QIODevice.WriteOnly)
        pixmap.save(buffer, 'PNG')
        return byte_array.data()

    @property
    def image_dims(self):
        return self.width(), self.height()

    def force_resize(self, qsize):
        self.resizeEvent(QResizeEvent(qsize, qsize))


class SelectablePixmap(ResizablePixmap):

    def __init__(self, bytes_image):

        super().__init__(bytes_image)

        self.currentQRubberBand = None
        self.move_rubber_band = False
        self.rubber_band_offset = None

    def cancel_selection(self):
        self.currentQRubberBand.hide()
        self.currentQRubberBand.deleteLater()
        self.currentQRubberBand = None
        self.selectionActive.emit(False)

    def mousePressEvent(self, eventQMouseEvent):

        if not self.currentQRubberBand:
            self.currentQRubberBand = ResizableRubberBand(self)
            self.selectionActive.emit(True)

        if self.currentQRubberBand.geometry().contains(eventQMouseEvent.pos()):
            self.move_rubber_band = True
            self.rubber_band_offset = (eventQMouseEvent.pos() -
                                       self.currentQRubberBand.pos())
        else:
            self.originQPoint = eventQMouseEvent.pos()
            if self.pixmap().rect().contains(self.originQPoint):
                self.currentQRubberBand.setGeometry(QRect(self.originQPoint,
                                                          QSize()))
                self.currentQRubberBand.show()

    def mouseMoveEvent(self, eventQMouseEvent):

        if self.move_rubber_band:
            pos = eventQMouseEvent.pos() - self.rubber_band_offset
            if self.pixmap().rect().contains(pos):
                self.currentQRubberBand.move(pos)
        else:
            rect = QRect(self.originQPoint, eventQMouseEvent.pos())
            self.currentQRubberBand.setGeometry(rect.normalized())

    def mouseReleaseEvent(self, eventQMouseEvent):

        if self.move_rubber_band:
            self.move_rubber_band = False

Tags: posimageselfnonebandmoveifbytes
2条回答

您可以将图像的宽度和高度(在从字节创建pixmap之前)存储到全局变量中,然后使用getter从类外部访问它。在

这个问题的“简单”答案是,您可以通过移动QPixmap的QRect来获得QPixmap的实际几何结构。由于使用的是中心对齐,因此非常简单:

pixmap_rect = self.pixmap.rect()
pixmap_rect.moveCenter(self.rect().center())

不幸的是,您不能只在实现中使用该矩形,主要是因为您没有真正使用QRubberBand。
使用大小手柄调整大小的儿童橡皮筋的概念很聪明,但也有很多局限性。
虽然QSizeGrips使调整大小变得更容易,但它们的行为不容易“限制”:您可能最终会尝试重新实现resize和{}(有递归风险),可能需要一些复杂复杂的鼠标事件检查。此外,您永远无法将“虚拟”橡胶带的大小调整为小于QSizeGrips大小总和的大小,也无法调整为“负”选择。
另外,在代码中,您永远不会调整实际的QRubberBand几何体的大小(但这可以在ResizableRubberBand.resizeEvent()内完成)。在

最后,即使在调整图像大小后还没有实现选择大小调整,如果执行了,也会有很多问题(主要是因为前面提到的最小大小限制)。在


我认为一个更好的解决方案是使用一个简单的QRubberBand并直接从使用它的小部件实现它的交互。这使您可以更好地控制它,还允许完整的调整大小功能(不仅是左上角和右下角)。
我稍微修改了您的基类代码,因为您应该避免在resizeEvent()内调整任何大小(即使在您的情况下它没有做任何事情,因为resize()的size参数是相同的),并且对_bytes2pixmap进行了不必要的调用。在

^{pr2}$

相关问题 更多 >

    热门问题