簡體   English   中英

如何使QLabel與其顯示的QPixmap的大小完全相同?

[英]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會“讓路”做標簽。結果是,我沒有左右“太多標簽”,而是“頂部和底部都有太多標簽”。我希望你明白我的意思。

我現在做的是:

  1. 將窗口大小調整為屏幕分辨率
  2. 添加(縮放)圖像
  3. 調整大小(0,0)

然后應用程序調整大小,以便Labe正好是圖像的大小(我想要的)但它是一種邪惡的,黑客的,閃爍的,瘋狂的方式來做它;-)

編輯:非常感謝你的答案,@ eyllanesc :-)我試過了,它完成了我想要的第一張照片。 我忘了提到的是,當第一張圖像被正確“橡皮化”時,點擊“下一步”按鈕后,會顯示另一張圖像。 如果此圖像小於實際標簽(或橫向而不是縱向),則標簽會縮小。 瞧,在一些具有不同分辨率和方向的圖像之后,標簽不斷縮小和縮小......

https://pastebin.com/ZMMw20Z7

https://giphy.com/gifs/xlou5RpQoX805fUymR

一種可能的解決方案是將大小的水平策略更改為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM