10

Consider the case of a QMainWindow with a QWidget as central widget. This widget has a QHBoxLayout. I add two other widgets to it, each with a QVBoxLayout.

I now want to bring the Widgets inside QVBoxLayout closer to each other. The attempt is to use .setMargin(0), .setSpacing(0) and .setContentsMargins(0,0,0,0) for this purpose.

However the result is that their separation is actually increased instead of decreased - as can be seen in the picture (where Gain is the widget where I set the margins and spacings to zero).

enter image description here

The code to reproduce this issue is appended below. (And the same actually happens when using a QGridLayout.)

Here is the question on two different complexity levels:

(a) Since the only difference between the two widgets is that one has the margins and spacings set to zero, one of the used method calls must have done something else to the layout or widget-properties. Which other property is changed by setting any of .setMargin(0), .setSpacing(0) and setContentsMargins(0,0,0,0) ?

(b) How do I make the spacing between the text label and the combobox in this example smaller?


from PyQt4 import QtGui
import sys

class LabeledComboBox(QtGui.QWidget):
    def __init__(self, text="", items=[], parent=None):
        super(LabeledComboBox, self).__init__(parent)
        self.parent = parent
        self.widgetlayout = QtGui.QVBoxLayout(self)
        self.widgetlayout.addWidget(QtGui.QLabel(text))
        self.Combo = QtGui.QComboBox()
        self.Combo.addItems(items)
        self.widgetlayout.addWidget(self.Combo)
        self.parent.mylayout.addWidget(self)

    def printParams(self):
        # print some margin/spacing parameters for testing
        m = self.widgetlayout.margin()
        s = self.widgetlayout.spacing()
        cm = self.widgetlayout.getContentsMargins()
        print "margin: {m}, spacing: {s}, ContentsMargin: {cm}".format(m=m, s=s, cm=cm)

class App(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(App, self).__init__(parent)
        self.mainbox = QtGui.QWidget()
        self.mylayout = QtGui.QHBoxLayout()
        self.mainbox.setLayout(self.mylayout)
        self.setCentralWidget(self.mainbox)

        self.GainWidget = LabeledComboBox("Gain", ['low', 'medium', 'high'],  self)
        self.RevolutionsWidget = LabeledComboBox("Revolutions", ['100', '200', '400'],  self)


        self.GainWidget.printParams()
        # this outputs: margin: 9, spacing: 6, ContentsMargin: (9, 9, 9, 9)
        # now I set everything to zero 
        self.GainWidget.widgetlayout.setMargin(0)
        self.GainWidget.widgetlayout.setSpacing(0)
        self.GainWidget.widgetlayout.setContentsMargins(0,0,0,0)
        # check
        self.GainWidget.printParams()
        # margin: 0, spacing: 0, ContentsMargin: (0, 0, 0, 0)


if __name__=='__main__':
    app = QtGui.QApplication(sys.argv)
    thisapp = App()
    thisapp.show()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712

2 Answers2

12

Firstly: setMargin is an obsolete method which has beed superseded by setContentsMargins, so you can ignore it.

Secondly: the increase in separation is caused by setting the margins to zero. The two vertical layouts are in the same horizontal layout, so they will necessarily have the same height. But the left-hand layout has no margins, so it has more space available to stretch out in. If both vertical layouts have the same settings, their child widgets can be squeezed closer together by resizing the window.

So you need to use setSpacing on both layouts to change the spacing.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • 1
    That is actually a nice explanation. I didn't think about this. What it means in the end is that one needs to add `.addStretch(1)` to the `QVBoxLayout` to make the effect of `.setSpacing(0)` effective. – ImportanceOfBeingErnest Oct 07 '16 at 21:17
  • 1
    @ImportanceOfBeingErnest. Yes, I was going to add a PS about `addStretch`, but now you saved me the bother :-) – ekhumoro Oct 07 '16 at 21:52
11

In the latest PyQt 5.10 setContentsMargins method is working well. You may create a layout for your widget and then apply its margins.

widget.layout.setContentsMargins(0,0,0,0)

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Pixsa
  • 571
  • 6
  • 16