0
votes

I have a QHBoxLayout which I add widgets to, one by one.
I alternate by adding a Custom Widget, than a QLabel (repeating).
The QHBoxLayout is owned by a QGroupBox.

However, I notice that the spacing between the Custom Widget and the QLabel is 'irregular' when there are few widgets added to the Layout.

I intend for the QLabels to be centered in the gap between the custom widgets, but the QLabels only approach the centre as more widgets are added.

These screenshots show the two cases.
The desired case (only occuring with lots of widgets in the layout),
and the undesired case (occuring when little widgets are in the layout).

Irregular Spacing in the bottom case, fine in the top.

As you can see in the bottom case, the QLabels are not centered between the Custom Widgets. Instead, they are very far to the right!

What is causing this behaviour??

I believe the QGroupBox has a centered (horizontal) alignment and the QLabels have a fixed width of 10 (or 20 for the '->' QLabel) pixels (to avoid ugly overlap).

Any help at all would be greatly appreciated!
Thanks!

Specs:
python 2.7.1
PyQt4
Windows 7

The instantiation of the QHBoxLayout is absolutely normal and similiar to all examples.
Here is the code for the filling of the layout.

for i in range (0,len(Reactants)):

    self.WidgetHouse.Reaction_Element_Layout.addWidget(eval('self.OverallContainer_Reactants.Reactant_'+str(i)))

    # self.WidgetHouse.Reaction_Element_Layout           is the QHBoxLayout
    # self.OverallContainer_Reactants.Reactant_'+str(i)       is a Custom Widget

    if i != (len(Reactants)-1):
        tmp = QtGui.QLabel('+')
        tmp.setFixedWidth(10)
        tmp.setAlignment(QtCore.Qt.AlignCenter)
        self.WidgetHouse.Reaction_Element_Layout.addWidget(tmp)

    else:
        tmp = QtGui.QLabel('->')
        tmp.setFixedWidth(20)
        tmp.setAlignment(QtCore.Qt.AlignCenter)
        self.WidgetHouse.Reaction_Element_Layout.addWidget(tmp)

EDIT:

Setting a fixed width of the QLabels (tmp.setFixedWidth(10)) is the source of the 'right anchoring'.
However, not setting a fixed width results in the same space being dedicated to QLabels and Custom Widgets in the layout, leading to an overlap of QLabels and Custom Widgets.

Fixed Width Labels vs Layout modulated widths

Identical to the code above, discluding 'tmp.setFixedWidt(10)'

What can I do to prevent this that's not completely horrible?
Can I move the Labels 'back' from the front?
(Calling .raise_() on all the custom widgets after everything was added to the layout did not work)

(Or will I have to do something like manually calculate the appropriate width of the labels based off the amount of widgets in the layout? Yuck!)

ANOTHER EDIT:

Progress:

I do not change the maximum/minimum (or fixed) width of the QLabels, but I do set their alignment to center.
Instead, I set a minimum width of the custom widget.
This fixes the apparent 'overlapping' (which wasn't really the case) and makes the Labels appear 'more centered'.

However, as you can see, the QLabels still aren't perfectly centered - too far right.
If I don't set a center alignment on the QLabels they are too far left.

What could be the problem now??

Overlapping solved, anchoring still an issue

(I do not set a maximum width on the labels)

Thanks for all the help so far guys!

2
There's a property called something like expanding that governs resizing behaviour. You might want to have a play around it Qt designer.Thomas K
I'm uncertain of what that means. Is it a QProperty, or a property of a particular Widget (ie: The Layout or the QLabel?)?Anti Earth
It's a property of your widgets - both the labels and your custom widgets, I expect. Oh, and it's called sizePolicy - my mistake.Thomas K
There must be something missing from your explanation, because I can't reproduce this on either Linux or Windows. The second image makes no sense based on the code you've shown, because the widgets should just automatically size themselves to fill the available space. There should be no need to fix the width of the labels, or change the size policy of any of the widgets. My best guess is that there's a redundant spacer item on the right-hand side of the custom widgets.ekhumoro
There aren't any spacer items! :( I had to fix the width of the labels because if I don't, when the layout has become quite populated, the QLabels start to overlap the custom widgets (with nothing, since the geometry of the QLabel is larger than the text?).Anti Earth

2 Answers

2
votes

Here is a simple example script which is a reasonable approximation of the UI in the question, but without any of the layout issues:

from PyQt4 import QtGui, QtCore

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.groupBox = QtGui.QGroupBox(self)
        hbox = QtGui.QHBoxLayout(self.groupBox)
        length = 3
        for index in range(length):
            hbox.addWidget(Widget(u'H\u2082O', self))
            if index < length - 1:
                hbox.addWidget(Label(u'+', self))
            else:
                hbox.addWidget(Label(u'\u2192', self))
        hbox.addWidget(Widget(u'4 H\u2082O', self))
        hbox.addWidget(Label(u'+', self))
        hbox.addWidget(Widget(u'H\u2084O\u2082', self))
        vbox = QtGui.QVBoxLayout(self)
        vbox.addWidget(self.groupBox)
        vbox.addStretch()

class Label(QtGui.QLabel):
    def __init__(self, label, parent=None):
        QtGui.QLabel.__init__(self, label, parent)
        self.setAlignment(QtCore.Qt.AlignCenter)

class Widget(QtGui.QWidget):
    def __init__(self, label, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setMaximumWidth(100)
        layout = QtGui.QGridLayout(self)
        self.label = QtGui.QLabel(label, self)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        layout.addWidget(self.label, 0, 0, 1, 2)
        self.lineEdit = QtGui.QLineEdit(self)
        layout.addWidget(self.lineEdit, 1, 0, 1, 2)
        self.toolButton = QtGui.QToolButton(self)
        layout.addWidget(self.toolButton, 2, 0, 1, 1)
        self.comboBox = QtGui.QComboBox(self)
        layout.addWidget(self.comboBox, 2, 1, 1, 1)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())
0
votes

Solution to all problems:

Give the custom widgets a fixed width.

Results in perfectly centered, not 'overlapping' widgets.
:)

Thanks for all the help guys!