Как создать полупрозрачный градиент?

В главный контейнер main_box я добавляю кнопку btn и цветной контейнер box.

В box добавляю два виджета:

  1. back_picture - изображение, которое располагается в верхней части контейнера, полученное с помощью класса BackPicture. Кнопка btn, привязанная к методу remake класса MyWindow, меняет картинку в back_picture.
  2. Надпись label, которая указывает на то, что back_picture не является единственным виджетом контейнера box.

Окно приложения:

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

Сейчас мне нужно наложить на back_picture градиент с особыми характеристиками:

  1. Вертикальный
  2. Крайняя нижняя точка имеет цвет #2A303D и 100% непрозрачности
  3. Крайняя верхняя точка имеет цвет #2A303D и 50% непрозрачности
  4. Очень важно! Центр градиента не расположен посередине, т.е. нижняя и верхняя точки неравноправны. Центр градиента смещен в сторону верхней точки, значит, нижняя занимает доминирующее положение. Обозначил точку центра градиента красной стрелкой.

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

Нарисовал картинку, которая показывает разницу наглядно. Цифрой 1 обозначил градиент со смещенным центром(как мне надо), цифрой 2 обозначил градиент без смещенного центра(как мне НЕ надо):

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

Градиент с цифрой 1 является моей целью

Покажу цветом, как градиент может быть смещен в сторону какой-либо точки, чтобы было понятнее. В первом случае градиент смещен в сторону нижней точки, во втором случае - в сторону верхней точки:

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

Работая в illustrator'е я заметил, что png запоминает уровень прозрачности пикселя. Это натолкнуло меня на мысль, что картинку градиента можно просто сохранить и расположить над back_picture.

Картинка градиента:

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

Если открыть эту картинку в каком-нибудь графическом редакторе, полупрозрачные пиксели будут действительно полупрозрачными. Но, к моему большому разочарованию, в окне приложения градиент отображается сплошным квадратом цвета #2A303D:

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

Мне нужно как-то создать градиент с точно такими же характеристиками и расположить его ровно над back_picture(важно, чтобы не было видно стыков), сохранив возможность менять изображение в back_picture. Пожалуйста, помогите мне сделать это

from PyQt5 import QtCore, QtWidgets, QtGui

class BackPicture(QtWidgets.QLabel):
    def __init__(self, picture, x, *args, **kwargs):
        super(BackPicture, self).__init__(*args, **kwargs)
        self.setFixedSize(x, x)
        self.x = x
        self.setPicture(picture)

    def setPicture(self, picture):
        self.setPixmap(QtGui.QPixmap(picture).scaled(self.x, self.x, QtCore.Qt.KeepAspectRatio))


class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.index = 1

        btn = QtWidgets.QPushButton('Remake', clicked = self.remake)

        self.container = QtWidgets.QWidget()
        self.container.setStyleSheet('background: #2A303D;')
        self.container.setMinimumHeight(300)
        self.container.setFixedWidth(300)

        main_box = QtWidgets.QHBoxLayout(self)
        main_box.addWidget(btn)        
        main_box.addWidget(self.container)

        box = QtWidgets.QVBoxLayout(self.container)
        box.setContentsMargins(0, 0, 0, 0)

        self.back_picture = BackPicture('picture3.jpg', 300, self.container)
        self.back_picture.move(0, 0)

        #self.gradient = BackPicture('gradient.png', 300, self.container)
        #self.gradient.move(0, 0)   НЕ РАБОТАЕТ

        label = QtWidgets.QLabel('Text number 1')
        label.setStyleSheet(qss)
        box.addStretch(6)
        box.addWidget(label, alignment = QtCore.Qt.AlignCenter)
        box.addStretch(1)

    def remake(self):
        if self.index == 1:
            self.back_picture.setPicture('picture2.png') 
            self.index = 2
        else:
            self.back_picture.setPicture('picture3.jpg') 
            self.index = 1


qss = '''QLabel {
             color: white;
             font: bold 16px;
             background: transparent;
         }'''

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

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

Автор решения: MAXIM045

Реализовать примерно такой градиент можно следующим образом(значения в таблице стиля лучше выставлять по своему усмотрению):

from PyQt5 import QtCore, QtWidgets, QtGui

class BackPicture(QtWidgets.QLabel):
    def __init__(self, picture, x, *args, **kwargs):
        super(BackPicture, self).__init__(*args, **kwargs)
        self.setFixedSize(x, x)
        self.x = x
        self.setPicture(picture)

    def setPicture(self, picture):
        self.setPixmap(QtGui.QPixmap(picture).scaled(self.x, self.x, QtCore.Qt.KeepAspectRatio))


class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.index = 1

        btn = QtWidgets.QPushButton('Remake', clicked = self.remake)

        self.container = QtWidgets.QWidget()
        self.container.setStyleSheet('background: #2A303D;')
        self.container.setMinimumHeight(300)
        self.container.setFixedWidth(300)

        main_box = QtWidgets.QHBoxLayout(self)
        main_box.addWidget(btn)        
        main_box.addWidget(self.container)

        box = QtWidgets.QVBoxLayout(self.container)
        box.setContentsMargins(0, 0, 0, 0)

        self.back_picture = BackPicture('white.png', 300, self.container)
        self.back_picture.move(0, 0)

        gradient = QtWidgets.QLabel(self.container)
        gradient.setFixedSize(300, 300)
        gradient.setStyleSheet(gradient_qss)
        gradient.move(0, 0)

        label = QtWidgets.QLabel('Text')
        label.setStyleSheet(label_qss)
        box.addStretch(1)
        box.addWidget(label, alignment = QtCore.Qt.AlignCenter)
        box.addStretch(1)

    def remake(self):
        if self.index == 1:
            self.back_picture.setPicture('picture1.png') 
            self.index = 2
        else:
            self.back_picture.setPicture('picture3.jpg') 
            self.index = 1

gradient_qss = '''QLabel {
                      background-color: qlineargradient(spread:pad,
                      x1:1, y1:1, x2:1, y2:0,
                      stop:0 rgb(42, 48, 61),
                      stop:0.05 rgb(42, 48, 61),
                      stop:0.1 rgb(42, 48, 61),
                      stop:0.15 rgba(42, 48, 61, 0.999),
                      stop:0.2 rgba(42, 48, 61, 0.998),
                      stop:0.25 rgba(42, 48, 61, 0.997),
                      stop:0.3 rgba(42, 48, 61, 0.996),
                      stop:0.35 rgba(42, 48, 61, 0.995),
                      stop:0.4 rgba(42, 48, 61, 0.99),
                      stop:0.45 rgba(42, 48, 61, 0.985),
                      stop:0.5 rgba(42, 48, 61, 0.98),
                      stop:0.55 rgba(42, 48, 61, 0.975),
                      stop:0.6 rgba(42, 48, 61, 0.97),
                      stop:0.65 rgba(42, 48, 61, 0.96),
                      stop:0.7 rgba(42, 48, 61, 0.95),
                      stop:0.75 rgba(42, 48, 61, 0.93),
                      stop:0.8 rgba(42, 48, 61, 0.9),
                      stop:0.85 rgba(42, 48, 61, 0.85),
                      stop:0.9 rgba(42, 48, 61, 0.8),
                      stop:0.95 rgba(42, 48, 61, 0.75),
                      stop:1 rgba(42, 48, 61, 0.7));
                  }'''

label_qss = '''QLabel {
                   color: white;
                   font: bold 16px;
                   background: transparent;
            }'''


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle(' ')
    window.show()
    sys.exit(app.exec_())
→ Ссылка