我正在尝试构建一个topBar
来放入其他小部件layout
但我不知道为什么'QPixmap在我们更改应用程序窗口大小时没有重新缩放。代码如下:
QPixmap
在QLabel
QWidget
的QHBoxLayout
范围内,QMainWindow
centralWidget
QT 5.8 - 蟒蛇 3.6
我已经在2017年3月24日更新了此代码并删除了以前的版本。
0 - 依赖项
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
1 - 主窗口
class MainWindow(QMainWindow):
def __init__(self):
print("I've been in main window")
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("I'm here, the main window")
2 - 顶栏
class topBar(QWidget):
def __init__(self):
print("I've been in topBar")
super().__init__()
self.initUI()
def initUI(self):
self.setObjectName("topBar")
self.setStyleSheet("""
QWidget {background-color: pink;}
QLabel {background-color: green; }""")
def resizeEvent(self,event):
resizeHandler(self,event) # You'll see this little dude right next
3 - resizeEvent
处理程序,我相信问题是
def resizeHandler(self,event):
print(" I've been in resizeHandler")
if self.objectName() == "topBar":
print("I've been resizing the topBar")
logo = QPixmap('some_Image')
# Debug
# You'll be able to see that it does re-scale, but it's not updating the Pixmap.
logo.scaled(event.size(),Qt.KeepAspectRatio).save("pixmap.png")
# ...
logoContainer = QLabel()
logoContainer.setPixmap(logo.scaled(event.size(),Qt.KeepAspectRatio,Qt.FastTransformation))
logoContainer.setMaximumSize(logo.width(),logo.height())
containerLayout = QHBoxLayout()
containerLayout.addWidget(logoContainer,0)
container = QWidget()
container.setLayout(containerLayout)
# Layout
layout = QHBoxLayout()
layout.addWidget(container,0)
self.setLayout(layout)
main.setCentralWidget(self)
4 - 测试
if __name__ == '__main__':
print("I've been in __main__")
app = 0
app = QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)
app.setWindowIcon(QIcon('someIcon'))
main = MainWindow()
main.layout().setSizeConstraint(QLayout.SetNoConstraint)
bar = topBar()
main.setCentralWidget(bar)
main.show()
app.exec_()
如果可能的话,我还想topBar
限制它self
垂直不超过当前屏幕尺寸的 20%(setMaximumHeight
?但基于什么?但我不确定如何。
谢谢!
若要获取小组件以填充容器,您需要将垂直和水平大小策略设置为最小、展开、最小展开或忽略。 http://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum
至于第二个问题,它不是Qt小部件的内置功能。你可能会得到更好的运气与QML或Web引擎。你可以创建一个QWidget的子类,它使用setGeometry((和一些窗口计算来约束它的大小。
我认为您在尝试诊断问题时在这里看错了东西。
您的最后一条评论指出...
真正的问题是QPixmap没有更新其大小
这是因为显示它的QLabel
没有调整大小。 回到您的原始代码,我认为您需要做的就是在container
和QLabel
logo
之间插入布局......
class topBar(QWidget):
def __init__(self,parent):
super().__init__()
container = QWidget()
container.setMaximumSize(587,208)
container.setMinimumSize(0,0)
## Logo
logo = QLabel(container)
#logo = QLabel(container_layout)
logo.setPixmap(QPixmap('.some_image_in_the_current_working_dir.png'))
logo.setScaledContents(1)
# G.M.
container_layout = QHBoxLayout(container)
container_layout.addWidget(logo)
# Layout
## to center content horizontally in wrapper w/o preventing rescale
layout = QHBoxLayout(self)
layout.addWidget(container)
self.setStyleSheet("""
QWidget {background-color: red;}
QLabel {background-color: green; Qt::KeepAspectRatio;}""")
if __name__ == '__main__':
app = 0
app = QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)
test = topBar(None)
test.show()
app.exec_()
(寻找通用汽车的评论(
上面的代码只是为container
创建一个布局container_layout
,并使logo
成为它的子项。 这似乎解决了我认为您所描述的问题。
经过大量的调试和阅读,我想出了以下解决方案(使用numpy
来帮助重新缩放(:
def resizeHandler(self,event):
if self.objectName() == "topBar":
# Wiping the old layout
temp = QWidget()
temp.setLayout(self.layout())
# Pixmap
logoPixmap = QPixmap('./img/exampleImage.png')
# Label
logoLabel = QLabel()
logoLabel.setPixmap(logoPixmap)
logoLabel.setScaledContents(True)
## Label Container Layout
containerLayout = QHBoxLayout()
containerLayout.addWidget(logoLabel,0)
# Label Container
logoContainer = QWidget()
logoContainer.setLayout(containerLayout)
# Finding the width and height of the scaled box
# Image unit vectors
imageSize = np.array((logoPixmap.width(),logoPixmap.height()))
screenSize = np.array((event.size().width(),event.size().height()))
# Proportion of each dimension in relation to the smallest side
# Note that one will always be the unit vector and the other greater than a unit
screenUVec = screenSize / screenSize.min()
imageUVec = imageSize / imageSize.min()
# minBorder 11 is the distance between the Application vertical border and the central widget
# 22 is the minimum height where the CentralWidget begins to appear
# Which should vary according to the height of menubar and statsbar of the QMainWindow
minBorder = np.array([11,22]) *2
screenSize -= minBorder
for axis,size in enumerate(screenSize):
if size < 0:
screenSize[axis] = 0
maxSize = np.zeros(2)
# Ideal ratio based on the maxSide
ratio = int(round(screenSize[imageUVec.argmax()] / imageUVec.max() - 0.49999999))
if ratio >=1 and 0 not in screenSize: # Image is scalable on the current screen
maxSize[imageUVec.argmin()] = min(screenSize[imageUVec.argmin()],ratio) # We should add imageSize[imageUVec.argmin()] if we want to limit the maxSize to the maximum size of the image
maxSize[imageUVec.argmax()] = maxSize[imageUVec.argmin()] * imageUVec.max()
sizeUVec = maxSize / maxSize.min()
# Layout
layout = QHBoxLayout()
layout.addWidget(logoContainer,0)
logoLabel.setMaximumSize(QSize(maxSize[0],maxSize[1]))
self.setLayout(layout)
特别感谢@alexisdm,他在这里向我展示了我们应该首先擦拭旧布局。当我开始观看globals
时,我看到几个布局堆叠在一起。
至于重新缩放部分,我仍然经历了一条非常规的道路,但它的行为方式是我想要的。