Как расположить виджеты так, чтобы элемент одного контейнера немного перекрывал второй контейнер?

Мой код создает две кнопки self.btn1 и self.btn2. Визуально они представляют из себя простые картинки, которые я оставлю тут:

tab1.png

введите сюда описание изображения

tab2.png

введите сюда описание изображения

Эти кнопки попадают в вертикальный контейнер self.box2. Далее создается контейнер box3, который обладает цветным фоном. Мне необходимо, чтобы выступ с правого края картинки tab1.png на кнопке self.btn1 перекрыл контейнер box3(основная часть обоих кнопок(большой квадрат) должна прижаться к стенкам box3), то есть нужно, чтобы кнопка self.btn1 сдвинулась по горизонтали ровно на 20px в сторону контейнера box3:

введите сюда описание изображения

Основные части обоих кнопок должны находится ровно друг под другом, т.е., можно сказать, что подвинуться должен весь контейнер с кнопками. Конечно, можно вырезать необходимый выступ из изображения и добавить его в box3. Однако, такой способ мне не подходит. Также в контейнере box3 будут располагаться различные виджеты, т.е. выступ не должен никак влиять на расположение элементов данного контейнера. Хотелось бы, чтобы между кнопками и контейнером не появилось зазоров. Я не против другой иерархии контейнеров, главное, чтобы это визуально соответствовало картинке и масштабировалось, при изменении размеров окна. Пожалуйста, подскажите, как это сделать?

from PyQt5 import QtCore, QtGui, QtWidgets

class MyWindow(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super(MyWindow, self).__init__(*args, **kwargs)

        self.resize(200, 300)

        main_box = QtWidgets.QHBoxLayout(self)
        btn = QtWidgets.QPushButton('Main Box')
        main_box.addWidget(btn)

        box1 = QtWidgets.QHBoxLayout(spacing = 0)
        main_box.addLayout(box1)

        self.box2 = QtWidgets.QVBoxLayout()
        self.btn1 = self.make_btn('tab1.png', 70, 50)
        self.box2.addWidget(self.btn1)
        self.btn2 = self.make_btn('tab2.png', 50, 50)
        self.box2.addWidget(self.btn2)
        self.box2.addStretch(1)

        label = QtWidgets.QLabel('Color Box', alignment = QtCore.Qt.AlignCenter)

        box1.addLayout(self.box2)
        container = QtWidgets.QWidget()
        container.setStyleSheet("background-color: #7189DB;")
        box1.addWidget(container)
        box3 = QtWidgets.QVBoxLayout(container)

        box3.addWidget(label)

    def make_btn(self, picture, x, y):
        btn = QtWidgets.QPushButton()
        btn.setIcon(QtGui.QIcon(picture))
        btn.setFixedSize(x, y)
        btn.setIconSize(QtCore.QSize(x, y))
        btn.setStyleSheet(qss)
        return btn


qss = '''QPushButton {
             border: none;
             margin: 0px;
             padding: 0px;
         }'''


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Как вариант. Попробуйте нажимать на кнопки.

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *


class Container(QWidget):                                                      # +++
    def __init__(self, parent):                   
        super(Container, self).__init__(parent)
        self.parent = parent

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setBrush(QBrush(QColor(113, 137, 219)))
        painter.setPen(QPen(Qt.NoPen))
        painter.drawRect(0, 0, self.width(), self.height())            
        if self.parent._color:
            self.brush = QBrush(QColor(*self.parent._color))
            painter.setBrush(self.brush)
            painter.drawRect(0, self.parent._height, 20, 20)


class MyWindow(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super(MyWindow, self).__init__(*args, **kwargs)

        self._color = None                                                     # +++
        self._height = None                                                    # +++
        self.resize(200, 300)

        main_box = QtWidgets.QHBoxLayout(self)
        btn = QtWidgets.QPushButton('Main Box')
        main_box.addWidget(btn)

        box1 = QtWidgets.QHBoxLayout(spacing = 0)
        main_box.addLayout(box1)

        self.box2 = QtWidgets.QVBoxLayout()
#        self.btn1 = self.make_btn('tab1.png', 70, 50)
        self.btn1 = self.make_btn('tab1.png', 50, 50)                          # +++ 
        self.box2.addWidget(self.btn1)
        self.btn2 = self.make_btn('tab2.png', 50, 50)
        self.box2.addWidget(self.btn2)
        self.box2.addStretch(1)
        label = QtWidgets.QLabel('Color Box ', alignment = QtCore.Qt.AlignCenter)
        label.setMinimumWidth(100)
        box1.addLayout(self.box2)


        self.container = Container(self)                                        # - QtWidgets.QWidget()  
#        self.container.setStyleSheet("background-color: #7189DB;")  # #7189DB; # -
        box1.addWidget(self.container)

        box3 = QtWidgets.QVBoxLayout(self.container)
        box3.addWidget(label)


    def make_btn(self, picture, w, h):                                     # w, h
        btn = QtWidgets.QPushButton()
        btn.setObjectName(f'{picture[:4]}')                                # +++    
        btn.clicked.connect(lambda ch, btn=btn: self.onClicked(btn))       # +++                                        
        btn.setIcon(QtGui.QIcon(picture))
        btn.setFixedSize(w, h)
        btn.setIconSize(QtCore.QSize(w, h))
        btn.setStyleSheet(qss)
        return btn

# ++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv        
    def onClicked(self, btn):
        if btn.objectName() == 'tab1':
            self._color = (250, 137, 123)
            self._height = 15            
        elif btn.objectName() == 'tab2':
            self._color = (204, 171, 218)
            self._height = 65          
        self.container.repaint()
# ++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        


qss = '''QPushButton {
             border: none;
             margin: 0px;
             padding: 0px;
         }'''


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

tab1.png

введите сюда описание изображения

→ Ссылка