在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
您可以将图像的宽度和高度(在从字节创建pixmap之前)存储到全局变量中,然后使用getter从类外部访问它。在
这个问题的“简单”答案是,您可以通过移动QPixmap的
QRect
来获得QPixmap的实际几何结构。由于使用的是中心对齐,因此非常简单:不幸的是,您不能只在实现中使用该矩形,主要是因为您没有真正使用QRubberBand。}(有递归风险),可能需要一些复杂复杂的鼠标事件检查。此外,您永远无法将“虚拟”橡胶带的大小调整为小于QSizeGrips大小总和的大小,也无法调整为“负”选择。
使用大小手柄调整大小的儿童橡皮筋的概念很聪明,但也有很多局限性。
虽然QSizeGrips使调整大小变得更容易,但它们的行为不容易“限制”:您可能最终会尝试重新实现
resize
和{另外,在代码中,您永远不会调整实际的QRubberBand几何体的大小(但这可以在
ResizableRubberBand.resizeEvent()
内完成)。在最后,即使在调整图像大小后还没有实现选择大小调整,如果执行了,也会有很多问题(主要是因为前面提到的最小大小限制)。在
我认为一个更好的解决方案是使用一个简单的QRubberBand并直接从使用它的小部件实现它的交互。这使您可以更好地控制它,还允许完整的调整大小功能(不仅是左上角和右下角)。
^{pr2}$我稍微修改了您的基类代码,因为您应该避免在
resizeEvent()
内调整任何大小(即使在您的情况下它没有做任何事情,因为resize()
的size参数是相同的),并且对_bytes2pixmap
进行了不必要的调用。在相关问题 更多 >
编程相关推荐