3

I am using QHBoxLayout for layout. The breakdown is: pic.1 is what happens, pic.2 is what I want - widgets don't overlap and there is a gap between them. For pic.2, I created a Gap widget to stick between the existing widgets. But this is a cumbersome solution which implies extra maintenance (especially when I have more than two widgets to care for). Moreover, since B overlaps A, I think the newly added gap widget overlaps A as well, maybe according the fraction of its size. I am not so sure about this.

pic 1

pic 2

I tried using self.layout.addSpacing(10), but that doesn't work. The red widget shifts by 10 pixels from where it was before, not from the border of the widget on the left.

Note, too, that the contained widgets will all have some minimum width specification.

So, how can I add the space between two widgets like in pic.2?

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

class Gap(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setMinimumWidth(10)
        self.setMinimumHeight(1)

class Line(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        # Set layout

        self.layout = QHBoxLayout()
        self.setLayout(self.layout)

        # Set palette

        self.palette1 = QPalette()
        self.palette1.setColor(QPalette.Window, Qt.red)

        self.palette2 = QPalette()
        self.palette2.setColor(QPalette.Window, Qt.blue)

        self.palettebg = QPalette()
        self.palettebg.setColor(QPalette.Window, Qt.green)
        self.setAutoFillBackground(True)
        self.setPalette(self.palettebg)

        # Set labels

        self.label1 = QLabel(self)
        self.label1.setText("A")
        self.label1.setStyleSheet('font-size: 36pt;')
        self.label1.adjustSize()
        self.label1.setAutoFillBackground(True)
        self.label1.setPalette(self.palette1)
        self.label1.setMinimumSize(36, 36)

        self.label2 = QLabel(self)
        self.label2.setText("B")
        self.label2.move(30, 0)
        self.label2.setStyleSheet('font-size: 36pt;')
        self.label2.adjustSize()
        self.label2.setAutoFillBackground(True)
        self.label2.setPalette(self.palette2)
        self.label2.setMinimumSize(36, 36)

        self.gap = Gap()

        self.layout.addWidget(self.label1)
        # self.layout.addWidget(self.gap)
        # self.layout.addSpacing(10)
        self.layout.addWidget(self.label2)

class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5'
        self.left = 10
        self.top = 10
        self.width = 200
        self.height = 54
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.line = Line(self)
        self.line.resize(74, 54)
        self.line.move(50, 50)

        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)

    # CUSTOM
    app.setFont(QFontDatabase().font("Monospace", "Regular", 14))

    ex = App()
    sys.exit(app.exec_())

EDIT clarification, as requested: (1) suppose the size of the parent widget is too small (and cannot be resized), (2) the parent widget has QHBoxLayout with widgets A and B added to it, (3) the parent widget being too small, QHBoxLayout aranges the child widgets A and B such that they overlap each other like in the first picture. (4) Such overlap is undesirable, instead the widgets just need to be placed one after another, with no overlap, and with gap between them, like in picture 2. I don't know how to do this with QHBoxLayout.

EDIT 2 Here is a visual explanation.

The green here is the parent widget - not resizable by assumption. Widget A is added:

enter image description here

Add widget B:

enter image description here

Now, widget B is on top of A. I don't want it. I want this instead:

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
user3496846
  • 1,627
  • 3
  • 16
  • 28

1 Answers1

2

The minimumSize of the child widgets does not influence the minimumSize of the parent widget, and the use of the layout does not influence the minimumSize of the widget either. The layouts set the minimumSizeHint and sizeHint using as information the minimumSize of the widgets that handle plus other features such as the size and sizing policy. So in the first instance you must set the minimumSize of the parent widget to be the minimumSizeHint of it.

On the other hand the layout has a spacing by default so it is advisable to set it to 0.

class Line(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent, autoFillBackground=True)
        # Set palette
        palette1 = QPalette()
        palette1.setColor(QPalette.Window, Qt.red)

        palette2 = QPalette()
        palette2.setColor(QPalette.Window, Qt.blue)

        palettebg = QPalette()
        palettebg.setColor(QPalette.Window, Qt.green)
        self.setPalette(palettebg)

        # Set labels
        self.label1 = QLabel(text="A", autoFillBackground=True)
        self.label1.setStyleSheet('font-size: 36pt;')
        self.label1.setPalette(palette1)
        self.label1.setMinimumSize(36, 36)
        self.label1.adjustSize()

        self.label2 = QLabel(text="B", autoFillBackground=True)
        self.label2.setStyleSheet('font-size: 36pt;')
        self.label2.setPalette(palette2)
        self.label2.setMinimumSize(36, 36)
        self.label2.adjustSize()

        # Set layout
        layout = QHBoxLayout(self, spacing=0)
        layout.addWidget(self.label1)
        layout.addSpacing(10)
        layout.addWidget(self.label2)
        self.setMinimumSize(self.minimumSizeHint())
        # or
        # layout = QHBoxLayout(self, spacing=10)
        # layout.addWidget(self.label1)
        # layout.addWidget(self.label2)
        # self.setMinimumSize(self.minimumSizeHint())

enter image description here


Update:

The maximum size of the layout that can be handled is the size of the parent widget, so in its case it will compress not respecting the spaces, a solution is to set a widget that is the content, and in that to establish the layout, so the layout will stretch to the content widget with freedom.

class Line(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent, autoFillBackground=True)
        # Set palette
        palette1 = QPalette()
        palette1.setColor(QPalette.Window, Qt.red)

        palette2 = QPalette()
        palette2.setColor(QPalette.Window, Qt.blue)

        palettebg = QPalette()
        palettebg.setColor(QPalette.Window, Qt.green)
        self.setPalette(palettebg)

        # Set labels
        self.label1 = QLabel(text="A", autoFillBackground=True)
        self.label1.setStyleSheet('font-size: 36pt;')
        self.label1.setPalette(palette1)
        self.label1.setMinimumSize(36, 36)
        self.label1.adjustSize()

        self.label2 = QLabel(text="B", autoFillBackground=True)
        self.label2.setStyleSheet('font-size: 36pt;')
        self.label2.setPalette(palette2)
        self.label2.setMinimumSize(36, 36)
        self.label2.adjustSize()

        content_widget = QWidget(self)
        layout = QHBoxLayout(content_widget, spacing=10)
        layout.addWidget(self.label1)
        layout.addWidget(self.label2)
        content_widget.setFixedSize(content_widget.minimumSizeHint())

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks for the reply, but I can't resize the widget, it's size stays constant: "(1) suppose the size of the parent widget is too small (and cannot be resized)". This, by the way, and the fact that widgets can't overlap, implies that the widget B on the right will exceed the parent's borders. – user3496846 Jan 20 '19 at 06:29
  • "The child widget can have a part or is totally outside the size of the parent widget, what happens in that case is that the part that is outside the parent widget will not be drawn" - that's perfectly fine! I am making something of a [very custom] scrollable table, with, potentially, many cells. I am OK with them not being drawn, but I do need them structured nicely. – user3496846 Jan 20 '19 at 06:46
  • *but I can not resize the widget, it's size stays constant* - it's just a necessary assumption of the application. I have added EDIT 2, please check it out. – user3496846 Jan 20 '19 at 06:57
  • @user3496846 You tell me look at your edition, but I ask you what's wrong with my answer – eyllanesc Jan 20 '19 at 06:58
  • the wrong part is that it results in the widget being resized. I don't want the widget resized. – user3496846 Jan 20 '19 at 07:00
  • Ah, okay, that you must have said from the beginning. – eyllanesc Jan 20 '19 at 07:01