2

Probably a noob question, but I'm still learning PySide. So I'm trying to use QMainWindow which has a QFrame and the QFrame has two labels. I'm using QBoxLayouts on QMainWindow and QFrame. The problem is that when I set the QFrame to something like 200x200 then QMainWindow does not resize, it remains too small to display both labels. Correct me if I'm wrong but shouldn't QMainWindow automatically have the right size when using layouts? Additionaly when I output frame.sizeHint() then it outputs PySide.QtCore.QSize(97, 50) but I would expect it to be 200, 200.

The code below will reproduce the problem:

import sys
from PySide import QtGui


class MainWindow(QtGui.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()

        self.initUI()

    def initUI(self):

        #-------
        #CREATE WIDGETS
        #-------
        frame = QtGui.QFrame()
        frame.setStyleSheet("QFrame {background-color: yellow}")
        frame.setGeometry(0, 0, 200, 200)

        someLabel = QtGui.QLabel("SomeLabel")
        someOtherLabel = QtGui.QLabel("SomeOtherLabel")

        self.setCentralWidget(frame)

        #--------
        #CREATE LAYOUT
        #--------

        frameLayout = QtGui.QVBoxLayout()
        frameLayout.addWidget(someLabel)
        frameLayout.addWidget(someOtherLabel)
        frame.setLayout(frameLayout)

        mainLayout = QtGui.QVBoxLayout()
        mainLayout.addWidget(frame)
        self.setLayout(mainLayout)

        self.show()

def main():

    app = QtGui.QApplication(sys.argv)
    mainWindow = MainWindow()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

This is what happens after code is run:

enter image description here

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
flouwer
  • 327
  • 1
  • 4
  • 13
  • You're probably resizing too early, before Qt actually sets the default widget size. From your constructor, try to emit a signal connected to a slot using QueuedConnection and resize the dialog from the slot. resize will be done "later" and it should then work. – jpo38 Feb 09 '16 at 20:07

1 Answers1

3

A QMainWindow already has a top-level layout, so you should never set one yourself. All you need to do is set the central-widget, and then add a layout and widgets to that.

Your example can therefore be fixed like this:

    frame.setLayout(frameLayout)

    # get rid of these three lines
    # mainLayout = QtGui.QVBoxLayout()
    # mainLayout.addWidget(frame)
    # self.setLayout(mainLayout)

    self.show()

It's worth noting that there is possibly a bug/misfeature in PySide regarding this, because in PyQt your original script would print a useful error message:

QWidget::setLayout: Attempting to set QLayout "" on MainWindow "", which already has a layout

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thanks for your answer. I realize now, reading the docs, that I misunderstood the QMainWindow concept and it indeed has a layout set in place. I tought I could lay out different widgets (labels, tables etc.) between the menu bar and status bar as I wanted and needed to define one of them as a centralWidget, but now I see that I need to lay out the different widgets inside the centralWidget. I tried your solution and now both the labels fit inside the window, but the window size is still 97x50, not 200x200 (the size of the QFrame). Can you please explain why it is not 200x200? – flouwer Feb 10 '16 at 18:10
  • @flouwer. You should to set the geometry of the main window (i.e. `self`), rather than the central widget. The geometry of the child widgets is determined by the layouts, but you can control that by setting their minimum, maximum or fixed sizes. – ekhumoro Feb 10 '16 at 19:38