我需要有关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_())
问题是,图像将显示在“标签”的中央,周围有很多“多余的标签”,请参见屏幕截图,红色的东西
但是我需要标签的尺寸精确到图像的尺寸。我想在图像上做一些橡皮筋处理,以选择它们的一部分(选择框供以后在retinanet训练中使用),并计算出需要mapToGlobal和mapFromGlobal的框的正确大小。我无法从Pixmap本身执行此操作(因为它不是窗口小部件),而当我从Label执行此操作时,由于它大于实际图像,因此我得到了错误的值。
现在,我可以将GridLayout或HBoxLayout与SpacerItems一起使用。问题在于逻辑。标签的大小(和UI加载时,SpacerItems会得到确定。当我以后动态添加图像时,即使只有SpacerItems会“给出方式”,它也会缩放到Label的大小,即使它可能更大)。做标签,结果是,我没有在左右两边设置“太多标签”,而是在顶部和底部有了“太多标签”。我希望你明白我的意思。
我目前要做的是:
然后调整应用程序的大小,以使Labe恰好是图像的大小(我想要的),但这是一种邪恶,骇人,闪烁,疯狂的方式;-)
编辑: 非常感谢您的回答,@eyllanesc :-) 我试过了,它满足了我对第一张照片的要求。我忘记提及的是,当第一个图像正确地“橡皮筋化”时,在单击“下一步”按钮后,将显示另一个图像。如果此图像小于实际标签(或横向而不是纵向),则标签会缩小。瞧,看到一些分辨率和方向不同的图像后,标签会不断缩小...
答案 0 :(得分:3)
一种可能的解决方案是将大小的水平策略更改为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_())