Как отображать формы на картинке в PyQt5?

Имеется:

Недоделанная программа-игра, похожая на Duck Hunt. Имеются 3 линии форм: для начала и остановки игры, выбора режима скорости и результатов. В самом низу расположена картинка-поле для будущих уток.

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

Проблема:

Реализацию уток я оставляю на кнопку (накладываю картинку утки на кнопку) и потом эту кнопку буду двигать, не суть. В общем, при попытке рисования на данной картинке кнопки (для будущей утки) = она появляется справа (приложил картинку), а НЕ на самой картинке-поле внутри.

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

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

Код:

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QLabel, QHBoxLayout, QVBoxLayout, QLineEdit, QFormLayout, QGroupBox, QRadioButton, QMainWindow, QWidget, QGridLayout, QApplication
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont, QPainter, QColor, QPixmap, QIcon

WINDOW_HEIGHT = 600
WINDOW_WIDTH = 600
WINDOW_NAME = 'Истребитель уток'
WINDOW_ICON_NAME = 'Images\\main_logo.png'

MAIN_FONT = 'Times'
FONT_HEADER_SIZE = 13
FONT_BODY_SIZE = 8


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

        self.create_all_forms()
        self.fill_forms()
        self.create_layers()

    def create_all_forms(self):
        self.task_label = QLabel()

        self.control_label = QLabel()
        self.start_button = QPushButton()
        self.quit_button = QPushButton()

        self.mode_label = QLabel()
        self.first_rbutton = QRadioButton()
        self.second_rbutton = QRadioButton()
        self.third_rbutton = QRadioButton()

        self.results_label = QLabel()
        self.play_time_qedit = QLineEdit(placeholderText="Время игры")
        self.play_attempts_qedit = QLineEdit(placeholderText="Число попыток")

        self.background_image_label = QLabel()
        background_image = QPixmap("backimage.png")
        self.background_image_label.setPixmap(background_image)

    def fill_forms(self):
        self.task_label.setText("Задача: убейте всех уток за установленное время.")
        self.task_label.setFont(QFont(MAIN_FONT, FONT_HEADER_SIZE))
        self.task_label.setAlignment(Qt.AlignCenter)

        self.control_label.setText("Управление")
        self.start_button.setText("Начать игру")
        self.quit_button.setText("Закончить игру")

        self.mode_label.setText("Режим:")
        self.mode_label.setFont(QFont(MAIN_FONT, FONT_HEADER_SIZE))
        self.first_rbutton.setText("1-я скорость")
        self.first_rbutton.setChecked(True)
        self.second_rbutton.setText("2-я скорость")
        self.third_rbutton.setText("3-я скорость")

        self.results_label.setText("Результаты:")
        self.results_label.setFont(QFont(MAIN_FONT, FONT_HEADER_SIZE))
        self.play_time_qedit.setDisabled(True)
        self.play_attempts_qedit.setDisabled(True)

    def create_layers(self):
        outline = '''
                    QGroupBox {
                        margin-top: 2ex;
                    }
                    QGroupBox::title {
                        subcontrol-origin: margin;
                        left: 3ex;
                    }
                    '''

        main_layout = QVBoxLayout(self)

        task_layout = QHBoxLayout()
        task_layout.addWidget(self.task_label)
        main_layout.addLayout(task_layout)

        self.control_groupbox = QGroupBox(self.control_label.text())
        self.control_groupbox.setStyleSheet(outline)
        control_groupbox_layout = QHBoxLayout(self.control_groupbox)
        control_groupbox_layout.addWidget(self.start_button)
        control_groupbox_layout.addWidget(self.quit_button)
        main_layout.addWidget(self.control_groupbox)

        self.mode_groupbox = QGroupBox(self.mode_label.text())
        self.mode_groupbox.setStyleSheet(outline)
        mode_groupbox_layout = QHBoxLayout(self.mode_groupbox)
        mode_groupbox_layout.addWidget(self.first_rbutton)
        mode_groupbox_layout.addWidget(self.second_rbutton)
        mode_groupbox_layout.addWidget(self.third_rbutton)
        main_layout.addWidget(self.mode_groupbox)

        self.result_groupbox = QGroupBox(self.results_label.text())
        self.result_groupbox.setStyleSheet(outline)
        result_groupbox_layout = QHBoxLayout(self.result_groupbox)
        result_groupbox_layout.addWidget(self.play_time_qedit)
        result_groupbox_layout.addWidget(self.play_attempts_qedit)
        main_layout.addWidget(self.result_groupbox)

        background_image_layout = QHBoxLayout()
        background_image_layout.addWidget(self.background_image_label)
        main_layout.addLayout(background_image_layout)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)

        self.build_skeleton_with_basic_settings()
        self.create_and_connect_grid()

    def build_skeleton_with_basic_settings(self):
        self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
        self.setWindowTitle(WINDOW_NAME)
        self.setWindowIcon(QIcon(WINDOW_ICON_NAME))

    def create_and_connect_grid(self):
        self.main_grid = QGridLayout(self.centralWidget)
        form_builder_object = FormBuilder()
        self.main_grid.addWidget(form_builder_object, 0, 0, Qt.AlignTop)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())

Картинка-поле:

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


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

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

Попробуйте так:

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QLabel, QHBoxLayout, \
    QVBoxLayout, QLineEdit, QFormLayout, QGroupBox, QRadioButton, \
    QMainWindow, QWidget, QGridLayout, QApplication, QSizePolicy
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QFont, QPainter, QColor, QPixmap, QIcon

WINDOW_HEIGHT = 600
WINDOW_WIDTH = 600
WINDOW_NAME = 'Истребитель уток'
WINDOW_ICON_NAME = 'Images\\main_logo.png'
#WINDOW_ICON_NAME = 'Ok.png'

MAIN_FONT = 'Times'
FONT_HEADER_SIZE = 13
FONT_BODY_SIZE = 8


class FormBuilder(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.create_all_forms()
        self.fill_forms()
        self.create_layers()

    def create_all_forms(self):
        self.task_label = QLabel()

        self.control_label = QLabel()
        self.start_button = QPushButton()
        self.quit_button = QPushButton()

        self.mode_label = QLabel()
        self.first_rbutton = QRadioButton()
        self.second_rbutton = QRadioButton()
        self.third_rbutton = QRadioButton()

        self.results_label = QLabel()
        self.play_time_qedit = QLineEdit(placeholderText="Время игры")
        self.play_attempts_qedit = QLineEdit(placeholderText="Число попыток")

        self.background_image_label = QLabel()
        background_image = QPixmap("backimage.png")
        self.background_image_label.setPixmap(background_image)

    def fill_forms(self):
        self.task_label.setText("Задача: убейте всех уток за установленное время.")
        self.task_label.setFont(QFont(MAIN_FONT, FONT_HEADER_SIZE))
        self.task_label.setAlignment(Qt.AlignCenter)

        self.control_label.setText("Управление")
        self.start_button.setText("Начать игру")
        self.quit_button.setText("Закончить игру")

        self.mode_label.setText("Режим:")
        self.mode_label.setFont(QFont(MAIN_FONT, FONT_HEADER_SIZE))
        self.first_rbutton.setText("1-я скорость")
        self.first_rbutton.setChecked(True)
        self.second_rbutton.setText("2-я скорость")
        self.third_rbutton.setText("3-я скорость")

        self.results_label.setText("Результаты:")
        self.results_label.setFont(QFont(MAIN_FONT, FONT_HEADER_SIZE))
        self.play_time_qedit.setDisabled(True)
        self.play_attempts_qedit.setDisabled(True)

    def create_layers(self):
        outline = '''
            QGroupBox {
                margin-top: 2ex;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                left: 3ex;
            }
        '''

        main_layout = QVBoxLayout(self)

        task_layout = QHBoxLayout()
        task_layout.addWidget(self.task_label)
        main_layout.addLayout(task_layout)

        self.control_groupbox = QGroupBox(self.control_label.text())
        self.control_groupbox.setStyleSheet(outline)
        control_groupbox_layout = QHBoxLayout(self.control_groupbox)
        control_groupbox_layout.addWidget(self.start_button)
        control_groupbox_layout.addWidget(self.quit_button)
        main_layout.addWidget(self.control_groupbox)

        self.mode_groupbox = QGroupBox(self.mode_label.text())
        self.mode_groupbox.setStyleSheet(outline)
        mode_groupbox_layout = QHBoxLayout(self.mode_groupbox)
        mode_groupbox_layout.addWidget(self.first_rbutton)
        mode_groupbox_layout.addWidget(self.second_rbutton)
        mode_groupbox_layout.addWidget(self.third_rbutton)
        main_layout.addWidget(self.mode_groupbox)

        self.result_groupbox = QGroupBox(self.results_label.text())
        self.result_groupbox.setStyleSheet(outline)
        result_groupbox_layout = QHBoxLayout(self.result_groupbox)
        result_groupbox_layout.addWidget(self.play_time_qedit)
        result_groupbox_layout.addWidget(self.play_attempts_qedit)
        main_layout.addWidget(self.result_groupbox)

        background_image_layout = QHBoxLayout()
        background_image_layout.addWidget(self.background_image_label)
        main_layout.addLayout(background_image_layout)


class Label(QLabel):
    def __init__(self, path, w, h):
        super().__init__()
        self.setPixmap(QPixmap(path).scaled(w, h))


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)
        self.build_skeleton_with_basic_settings()
        self.create_and_connect_grid()
        
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv   
        self.my_widget = QWidget(self.form_builder_object.background_image_label)
        self.my_widget.setFixedWidth(self.size().width()-30)

        self.layout_left = QHBoxLayout()
        for i in range(2):
            label = Label("bullet.png", 10, 40) 
            self.layout_left.addWidget(label) 
        self.layout_left.addStretch(1)
        
        self.layout_center = QHBoxLayout() 
        self.layout_center.addStretch(1)
        self.button = QPushButton() 
        self.button.setFixedWidth(25)
        self.button.setIcon(QIcon("down.png"))
        self.button.setIconSize(QSize(20, 20))
        self.layout_center.addWidget(self.button)
        self.layout_center.addStretch(1)
        
        self.layout_right = QHBoxLayout()
        self.layout_right.addStretch(1)
        for i in range(2):
            label = Label("heart_.png", 30, 30) 
            self.layout_right.addWidget(label) 
            
        my_layout = QHBoxLayout(self.my_widget)      
        my_layout.addLayout(self.layout_left, 0)
        my_layout.addLayout(self.layout_center, 1)
        my_layout.addLayout(self.layout_right, 0)
        
        
        label = Label("bullet.png", 10, 40) 
        self.layout_left.insertWidget(0, label)
        
        label = Label("heart_.png", 30, 30) 
        self.layout_right.addWidget(label) 
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    def build_skeleton_with_basic_settings(self):
        self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
        self.setWindowTitle(WINDOW_NAME)
        self.setWindowIcon(QIcon(WINDOW_ICON_NAME))

    def create_and_connect_grid(self):
        self.main_grid = QGridLayout(self.centralWidget)
        self.form_builder_object = FormBuilder()                               # + self.
        self.main_grid.addWidget(self.form_builder_object, 0, 0, Qt.AlignTop)  # + self. 


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())

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

→ Ссылка