QT - QPixmap没有使用当前父级大小重新缩放

时间:2017-03-22 21:06:40

标签: qt python-3.x pyqt qt5 pyqt5

我正在尝试构建一个topBar以放入其他小部件layout,但我不知道为什么`QPixmap没有重新缩放,因为我们更改了应用程序窗口大小。这是代码:

QPixmap位于QLabel QHBoxLayout QWidget范围内,centralWidget <{1}}

QT 5.8 - Python 3.6

我已更新此代码并于2017年3月24日删除了之前的版本。

0 - 依赖

QMainWindow

1 - 主窗口

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

2 - 顶栏

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")

3 - 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 处理程序,我相信问题

resizeEvent

4 - 测试

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)

如果有可能我还希望将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限制为不超过当前屏幕尺寸的20%(self?但基于什么?)但我我不确定如何。

谢谢!

3 个答案:

答案 0 :(得分:0)

要使小部件填充容器,您需要将垂直和水平大小策略设置为最小,扩展,最小扩展或忽略。 http://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum

就第二个问题而言,它不是Qt小部件的内置功能。使用QML或Web引擎可能会更好运。你可以创建一个QWidget的子类,它使用setGeometry()和一些窗口计算来约束它的大小。

答案 1 :(得分:0)

我认为你在尝试诊断问题时会看到错误的东西。

您的上一条评论声明......

  

真正的问题是QPixmap没有更新其大小

那是因为显示它的QLabel没有调整大小。回到原始代码我认为您需要做的就是在containerQLabel 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_()

(寻找G.M.评论)

上面的代码只是为container_layout创建了一个布局container,并使logo成为了它的一个孩子。这似乎解决了我正在描述的认为的问题。

答案 2 :(得分:0)

经过大量的调试和阅读后,我想出了以下解决方案(使用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,他告诉我HERE我们应首先擦除旧布局。当我开始观看globals时,我看到堆叠了几个布局。

至于重新缩放的部分,我仍然经历了一条非传统的道路,但它表现得像我想要的那样。