Расположение одного виджета над другим, PyQt

Нужно чтобы пользователь мог рисовать поверх label.
Хотелось бы сделать не прибегая к Layout.

from PyQt6.QtWidgets import (QApplication, QWidget, QToolBar, QMainWindow, QLabel,
                             QScrollArea, QToolBar)
from PyQt6.QtGui import QImage, QAction, QKeySequence, QColor, QPixmap, QPainter, QPen
from PyQt6.QtCore import Qt, QPoint, QSize, QRect
from sys import argv


class Canvas(QLabel):
    def __init__(self):
        super().__init__()
        self.setStyleSheet("background-color: #E0FFFF")
        self.setScaledContents(False)
        pixmap = QPixmap(2000, 1000)
        pixmap.fill(QColor('transparent'))
        #QtCore.Qt.transparent
        #pixmap.fill(QtCore.Qt.transparent)
        self.setPixmap(pixmap)
        self.drawing = False
        self.last_coords = None
        self.test()

        

    def minimumSize(self):
        print(1)
        return QSize(500, 500)

    def set_drawing(self, drawing):
        self.drawing = drawing


    def mouseMoveEvent(self, e):
        if self.drawing:
            if self.last_coords is None:
                self.last_coords = e.position()
                return
            canvas = self.pixmap()
            painter = QPainter(canvas)
            pen = painter.pen()
            pen.setWidth(4)
            pen.setColor(QColor('black'))
            painter.setPen(pen)
            painter.drawLine(self.last_coords, e.position())
            painter.end()
            self.setPixmap(canvas)
            self.last_coords = e.position()

    def mouseReleaseEvent(self, e):
        self.last_coords = None

    def reziseEvent(self, e):
        print(1)
        super().resizeEvent(e)

    def test(self):
        label = QLabel('test', self)
        #label.setGeometry(QRect(self.geometry().left() + 50, 50, 50, 10))
        label.move(50, 50)
        self.show()

        
        

class NoteEditor(QMainWindow):
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle('Note editor')
        self.setGeometry(100, 100, 800, 600)

        self.toolbar = QToolBar('Интрументы')
        self.addToolBar(self.toolbar)

        is_drawing_action = QAction('Рисовать', self)
        is_drawing_action.setCheckable(True)
        is_drawing_action.triggered.connect(self.set_drawing_action)

        self.toolbar.addAction(is_drawing_action)

        
        widget = QWidget()
        scroll = QScrollArea()
        self.canvas = Canvas()
        scroll.setWidget(self.canvas)
        self.setCentralWidget(scroll)


    def set_drawing_action(self, state):
        print(state)
        self.canvas.set_drawing(state)
        
        

app = QApplication(argv)

window = NoteEditor()
window.show()

app.exec()

В документации нечего не смог найти на этот случай. Заранее спасибо!


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

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

Sorry, вы не достаточно хорошо описываете проблему и то что вы хотите сделать.

Вы и так рисуете поверх label, т.к. объект self.canvas это и есть переопределенный класс QLabel().

Вы видимо хотите чтобы в вашем примере рисовалось и поверх объекта label, который вы создаете в методе test().
Но так не получится, т.к. вы рисуете на объекте self.canvas, а объект label расположен над объектом self.canvas но другой плоскости.

Если реализовывать ваш пример, то добавочный текст, на котором вы также хотите рисовать - необходимо также рисовать на объекте self.canvas, используя drawText.
Добавление дополнительного текста, для демонстрации вышесказанного, я реализовал в методе mousePressEvent(self, event) по нажатию ПРАВОЙ кнопки мыши.

Теперь по добавленному тексту можно рисовать сверху и еще если вы кликните ПКМ по уже нарисованному, то этот текст отобразится поверх рисунка.

Поменяйте то что необходимо для PyQt6 и попробуйте:

'''
from PyQt6.QtWidgets import (QApplication, QWidget, 
    QToolBar, QMainWindow, QLabel, QScrollArea, QToolBar)
from PyQt6.QtGui import QImage, QAction, QKeySequence, \
    QColor, QPixmap, QPainter, QPen
from PyQt6.QtCore import Qt, QPoint, QSize, QRect
'''
import sys
from PyQt5.Qt import *


class Canvas(QLabel):
    def __init__(self):
        super().__init__()
        self.drawing = False
        self.last_coords = None
        self.leftButton = False                                # +++ 
        self.setStyleSheet("background-color: #E0FFFF")
        self.setScaledContents(False)
        
        pixmap = QPixmap(2000, 1000)
        pixmap.fill(QColor('transparent'))
        self.setPixmap(pixmap)

        self.test()
    
#?    def minimumSize(self):
#?        print(1)
#?        return QSize(500, 500)

    def set_drawing(self, drawing):
        self.drawing = drawing

    def mousePressEvent(self, event):
        if event.button() == Qt.RightButton:
            self.last_coords = event.pos()  
            canvas = self.pixmap()
            painter = QPainter(canvas)
            painter.setPen(QColor(250, 55, 55))
            painter.setFont(QFont('Decorative', 18))
            painter.drawText(self.last_coords, 
                f'вы кликнули: {self.last_coords.x()}/{self.last_coords.y()}')        
            painter.end()
            self.setPixmap(canvas)
        if event.button() == Qt.LeftButton:                     # +++ 
            self.leftButton = True                              # +++ 

    def mouseMoveEvent(self, e):
# ------------------------> vvvvvvvvvvvvvvv <-------------------# +++ 
        if self.drawing and self.leftButton:
            if self.last_coords is None:
#                self.last_coords = e.position()             # PyQt6
                self.last_coords = e.pos()                   # PyQt5
                return
            canvas = self.pixmap()
            painter = QPainter(canvas)
            pen = painter.pen()
            pen.setWidth(7)
            pen.setColor(QColor('black'))
            painter.setPen(pen)
#            painter.drawLine(self.last_coords, e.position()) # PyQt6
            painter.drawLine(self.last_coords, e.pos())       # PyQt5
            painter.end()
            self.setPixmap(canvas)
#            self.last_coords = e.position()                  # PyQt6
            self.last_coords = e.pos()                        # PyQt5

    def mouseReleaseEvent(self, e):
        self.last_coords = None
        self.leftButton = False                               # +++ 

# ------> v v <----------------------------------------------------
#   def reziseEvent(self, e):
    def resizeEvent(self, e):           # ??? для чего в этом классе
        print(f'resizeEvent(self, e): {e.size()}') 
        super().resizeEvent(e)

    def test(self):
        label = QLabel('<H2 style="color: rgb(250, 55, 55);">Hello test</H2>', self)
        label.move(50, 50)
        self.show()


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

        self.toolbar = QToolBar('Интрументы')
        self.addToolBar(self.toolbar)

        is_drawing_action = QAction('Рисовать', self)
        is_drawing_action.setCheckable(True)
        is_drawing_action.triggered.connect(self.set_drawing_action)

        self.toolbar.addAction(is_drawing_action)
        
# ?      widget = QWidget()
        scroll = QScrollArea()
        self.canvas = Canvas()
        scroll.setWidget(self.canvas)
        self.setCentralWidget(scroll)

    def set_drawing_action(self, state):
        #print(state)
        self.canvas.set_drawing(state)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = NoteEditor()
    window.setWindowTitle('Note editor')
    window.resize(800, 600)
    window.show()
    sys.exit(app.exec())

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

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

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

→ Ссылка
Автор решения: руслан шлынков

Нашёл решение с помощью использования lower и raise_. Главное чтобы располагались в одном родительском виджете. результат

Нужно было просто поднять PaintCanvas с помощью raise_. Спасибо кто помогал!

→ Ссылка