Как рисовать в отдельном виджете при помощи QPainter?

Как мне отрисовывать элементы при помощи QPainter в отдельном виджете?

Пробовал засовывать его напрямую в QPainter. Работает только с self, то есть с моим экзепляром класса.

from PyQt5.QtWidgets import QDialog, \
                        QVBoxLayout, \
                        QPushButton, \
                        QSpinBox, \
                        QHBoxLayout, \
                        QWidget
from PyQt5.QtGui import QPainter



class MainWindow(QDialog):
def __init__(self):
    super().__init__()
    
    self.resize(700, 800)
    self.setWindowTitle('Лабораторная номер 6')

    #// Create Widgets
    self.spinbox = QSpinBox(self)
    self.spinbox.setMinimum(1)
    self.spinbox.setMaximum(100)
    self.spinbox.move(50, 50)
    self.spinbox.setPrefix('Скорость: ')

    self.button_1 = QPushButton('Начать', self)
    self.button_2 = QPushButton('Выход', self)
    self.button_1.clicked.connect(self.draw)

    self.figure = QWidget(self) # <---- В этом виджете мне нужно редактировать
    self.figure.setStyleSheet('background-color: grey;')
    # self.canvas = QPainter(self.figure)
    # self.figure.setStyleSheet('background-color: blue;')

    #// Create Layout
    buttons_layout = QHBoxLayout()
    buttons_layout.addWidget(self.button_1)
    buttons_layout.addWidget(self.button_2)
    
    layout = QVBoxLayout()
    layout.addWidget(self.spinbox)
    layout.addWidget(self.figure)
    layout.addLayout(buttons_layout)        
    
    self.setLayout(layout)
    # self.canvas.begin(self.figure)
    # self.canvas.end()
   
def paintEvent(self, event):
    painter = QPainter(self)      
    painter.drawRect(100, 15, 30, 100)

def draw(self):
    pass

    

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

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

Создайте подкласс для виджета, в котором вы собираетесь рисовать и добавьте в нем paintEvent()

void QWidget::paintEvent(QPaintEvent *event)

Этот обработчик событий может быть повторно реализован в подклассе для получения событий рисования, передаваемых в событии.

Событие рисования — это запрос на перерисовку всего или части виджета. Это может произойти по одной из следующих причин:

  • была вызвана функция repaint() или update(),

  • виджет был скрыт, а теперь открыт, или

  • много других причин.

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


class Widget(QtWidgets.QFrame):
    def __init__(self, parent):
        super().__init__(parent)

        self.setStyleSheet('background-color: grey;')

        self.rand_ranges = [ random.randrange(1, 100) for _ in range(4) ]
        
    def paintEvent(self, event):
        painter = QPainter(self)      
        pen = QPen(Qt.red, 2, Qt.DashLine)
        painter.setPen(pen)
        painter.drawRect(* self.rand_ranges)        
        
        
class MainWindow(QDialog):
    def __init__(self):
        super().__init__()
        
        self.resize(700, 800)
        self.setWindowTitle('Лабораторная номер 6')

        #// Create Widgets
        self.spinbox = QSpinBox(self)
        self.spinbox.setMinimum(1)
        self.spinbox.setMaximum(100)
        self.spinbox.move(50, 50)
        self.spinbox.setPrefix('Скорость: ')

        self.button_1 = QPushButton('Начать', self)
        self.button_1.clicked.connect(self.draw)
        
        self.button_2 = QPushButton('Выход', self)

        self.figure = Widget(self)          # <---- В этом виджете мне нужно редактировать

        #// Create Layout
        buttons_layout = QHBoxLayout()
        buttons_layout.addWidget(self.button_1)
        buttons_layout.addWidget(self.button_2)
        
        layout = QVBoxLayout(self)
        layout.addWidget(self.spinbox)
        layout.addWidget(self.figure)
        layout.addLayout(buttons_layout)        
       
    def paintEvent(self, event):
        painter = QPainter(self)      
        pen = QPen(Qt.blue, 2, Qt.DashLine)
        painter.setPen(pen)
        painter.drawRect(100, 15, 30, 100)

    def draw(self):
        self.figure.rand_ranges = [ random.randrange(1, 200) for _ in range(4) ]
        self.figure.repaint()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

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

→ Ссылка