[英]How can I have a QLabel exactly the size of the QPixmap it is showing?
關於QT / PyQt中的布局,我需要一些建議。
我想要實現的是將圖像顯示,居中,縮放正確,在保持其縱橫比的同時占用盡可能多的空間。 這很容易用這個來完成:
class Demo(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowState(Qt.WindowMaximized)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.button = QPushButton("Next image")
self.label = QLabel()
self.label.setStyleSheet("QLabel { background-color : red; }")
self.label.setAlignment(Qt.AlignCenter)
self.layout.addWidget(self.label)
self.layout.addWidget(self.button)
self.button.clicked.connect(self.showImage)
self.show()
def showImage(self):
self.pixmap = QPixmap("image.jpg")
scaled = self.pixmap.scaled(self.label.size(), Qt.KeepAspectRatio)
self.label.setPixmap(scaled)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Demo()
sys.exit(app.exec_())
這個問題是,圖像將以標簽為中心顯示,周圍有很多“多余標簽”,請看截圖,紅色的東西
但我需要Label 完全符合圖像的大小。 我想在圖像上做一些橡皮筋選擇它們的一部分(選擇框以便以后用於視網膜訓練)並計算我需要mapToGlobal和mapFromGlobal的正確尺寸。 我不能從Pixmap本身那里做到這一點(因為它不是小部件),當我從Label執行時,我得到錯誤的值,因為它比實際圖像大。
現在,我可以使用GridLayout或帶有SpacerItems的HBoxLayout。 問題在於它的邏輯。 Label的大小(以及SpacerItems在UI加載時得到確定。當我稍后動態添加圖像時,它會縮放到Label的大小,即使它可能更大,如果只有SpacerItems會“讓路”做標簽。結果是,我沒有左右“太多標簽”,而是“頂部和底部都有太多標簽”。我希望你明白我的意思。
我現在做的是:
然后應用程序調整大小,以便Labe正好是圖像的大小(我想要的)但它是一種邪惡的,黑客的,閃爍的,瘋狂的方式來做它;-)
編輯:非常感謝你的答案,@ eyllanesc :-)我試過了,它完成了我想要的第一張照片。 我忘了提到的是,當第一張圖像被正確“橡皮化”時,點擊“下一步”按鈕后,會顯示另一張圖像。 如果此圖像小於實際標簽(或橫向而不是縱向),則標簽會縮小。 瞧,在一些具有不同分辨率和方向的圖像之后,標簽不斷縮小和縮小......
一種可能的解決方案是將大小的水平策略更改為QSizePolicy::Maximum
並將窗口小部件置於布局中心:
from PyQt5 import QtCore, QtGui, QtWidgets
class Demo(QtWidgets.QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowState(QtCore.Qt.WindowMaximized)
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton("Next image")
self.label = QtWidgets.QLabel()
self.label.setStyleSheet("QLabel { background-color : red; }")
layout.addWidget(self.label)
layout.addWidget(self.button)
self.button.clicked.connect(self.showImage)
self.show()
def showImage(self):
self.pixmap = QtGui.QPixmap("image.jpg")
scaled = self.pixmap.scaled(self.label.size(), QtCore.Qt.KeepAspectRatio)
self.label.setPixmap(scaled)
sp = self.label.sizePolicy()
sp.setHorizontalPolicy(QtWidgets.QSizePolicy.Maximum)
self.label.setSizePolicy(sp)
self.layout().setAlignment(self.label, QtCore.Qt.AlignCenter)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Demo()
sys.exit(app.exec_())
更新:
以前的解決方案的問題是前一個QLabel的大小被用作建立新大小的參考,而不是它應該基於它可能具有的最大大小,為此我已經實現了跟蹤大小的自定義類最大值:
from PyQt5 import QtCore, QtGui, QtWidgets
from itertools import cycle
from glob import glob
class Label(QtWidgets.QLabel):
def resizeEvent(self, event):
if not hasattr(self, 'maximum_size'):
self.maximum_size = self.size()
else:
self.maximum_size = QtCore.QSize(
max(self.maximum_size.width(), self.width()),
max(self.maximum_size.height(), self.height()),
)
super(Label, self).resizeEvent(event)
def setPixmap(self, pixmap):
scaled = pixmap.scaled(self.maximum_size, QtCore.Qt.KeepAspectRatio)
super(Label, self).setPixmap(scaled)
class Demo(QtWidgets.QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowState(QtCore.Qt.WindowMaximized)
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton("Next image")
self.label = Label()
self.label.setStyleSheet("QLabel { background-color : red; }")
layout.addWidget(self.label)
layout.addWidget(self.button)
self.button.clicked.connect(self.showImage)
self.show()
self.images = cycle(glob("images/*"))
def showImage(self):
try:
filename = next(self.images)
self.label.setPixmap(QtGui.QPixmap(filename))
sp = self.label.sizePolicy()
sp.setHorizontalPolicy(QtWidgets.QSizePolicy.Maximum)
self.label.setSizePolicy(sp)
self.layout().setAlignment(self.label, QtCore.Qt.AlignCenter)
except StopIteration:
pass
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Demo()
sys.exit(app.exec_())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.