为了账号安全,请及时绑定邮箱和手机立即绑定

在 QMainWindow 上显示的自定义 QGraphicsView 中的 PyQT 绘图

在 QMainWindow 上显示的自定义 QGraphicsView 中的 PyQT 绘图

浮云间 2021-11-09 13:42:58
基本思想是我不能在 QMainWindow 中使用 QGraphicsView 类进行绘制。我可以看到 painEvent 触发,并且信息正在流向执行绘图的方法,但最终没有显示任何内容。这是带有 QGraphicsView 的类:class Display_Pixels(QGraphicsView):    def __init__(self, parent=None):        QGraphicsView.__init__(self, parent=parent)        #super().__init__()        self.initUI()        self.img = cv2.imread('roi.jpg')    def initUI(self):              self.setGeometry(100, 100, 650, 650)        #self.setWindowTitle('By Pixel')        #self.setMouseTracking(True)        #self.show()        res = 40         self.grid = np.array([ [-1] * res  for n in range(res)]) # list comprehension        #print(self.grid.shape)    def paintEvent(self, e):        qp = QPainter()        qp.begin(self)        self.drawRectangles(qp)        qp.end()    def drawRectangles(self, qp, w = 16):        print("Drawing")        mode = 0        x,y = 0,0 # starting position        lr = 20        hr = 35        col = QColor(0, 0, 0)        col.setNamedColor('#d4d4d4')        qp.setPen(col)        #print(self.img.shape)        for g_row, img_row in zip(self.grid, self.img):            #print(img_row.shape)            for g_col, img_col in zip(g_row, img_row):                r, g, b = (img_col[0], img_col[1], img_col[2])                #print(r,g,b)                if g_col == 1:                    if mode == 0:                        r = int(math.log(r)*lr)                        g = int(math.log(g)*hr)                        b = int(math.log(b)*lr)                    elif mode == 1:                        if r+50 <= 220: r = r+50                        if g+80 <= 255: g = g+80                        if b+50 <= 220: b = b+50                    else:                        if r+70 <= 220: r = r+70                        if g+140 <= 255: g = g+140                        if b+70 <= 220: b = b+70
查看完整描述

1 回答

?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

QGraphicsView 继承自 QAbstractScrollArea 所以 QPainter 必须在 中设置viewport(),即:


def paintEvent(self, e):

    qp = QPainter()

    qp.begin(self.viewport())

    self.drawRectangles(qp)

    qp.end()

尽管我会绘制它并不是最好的,因为 QGraphicsView 有一个使用这些项目的绘制层。在这种情况下,最好实现一个自定义项目,我也改进了你的算法。:


import sys

import numpy as np

import cv2

from PyQt5 import QtCore, QtGui, QtWidgets


class OpenCVItem(QtWidgets.QGraphicsItem):

    def __init__(self, img, parent=None):

        super(OpenCVItem, self).__init__(parent)

        res = 40

        self.grid = -np.ones((res, res))

        self._img = img

        height, width, channel = self._img.shape

        bytesPerLine = 3 * width

        self._qimage = QtGui.QImage(self._img.data, 

            width, height, 

            bytesPerLine, 

            QtGui.QImage.Format_RGB888).rgbSwapped()


    def boundingRect(self):

        w, h, _ = self._img.shape

        return QtCore.QRectF(0, 0, w, h)


    def paint(self, painter, option, widget):

        painter.drawImage(0, 0, self._qimage)

        self.drawRectangles(painter)


    def drawRectangles(self, painter):

        mode = 0

        lr = 20

        hr = 35

        painter.save()

        painter.setPen(QtGui.QPen(QtGui.QColor("#d4d4d4")))

        w1, h1 = self.grid.shape

        fw = self.boundingRect().width()/w1

        fh = self.boundingRect().height()/h1

        s = QtCore.QSizeF(fw, fh)

        for idx, v in np.ndenumerate(self.grid):            

            if v == 1:

                r_ = QtCore.QRectF(fw*QtCore.QPointF(*idx), s)

                r_int = r_.toRect()

                (r, g, b), _ = cv2.meanStdDev(self._img[r_int.left():r_int.right(), 

                    r_int.top():r_int.bottom()])

                if mode == 0:

                    r = np.log(r+1)*lr

                    g = np.log(g+1)*hr

                    b = np.log(b+1)*lr

                elif mode == 1:

                    if r+50 <= 220: r = r+50

                    if g+80 <= 255: g = g+80

                    if b+50 <= 220: b = b+50

                else:

                    if r+70 <= 220: r = r+70

                    if g+140 <= 255: g = g+140

                    if b+70 <= 220: b = b+70

                painter.setBrush(QtGui.QColor(*(int(x) for x in (r, g, b))))

                painter.drawRect(r_)

        painter.restore()


    def mousePressEvent(self, event):

        w1, h1 = self.grid.shape

        fw = self.boundingRect().width()/w1

        fh = self.boundingRect().height()/h1

        xi = int(event.pos().x()/fw) 

        yi = int(event.pos().y()/fh)

        self.grid[xi][yi] = -self.grid[xi][yi]

        self.update()

        super(OpenCVItem, self).mousePressEvent(event)


class Display_Pixels(QtWidgets.QGraphicsView):

    def __init__(self, parent=None):

        super(Display_Pixels, self).__init__(parent)

        scene = QtWidgets.QGraphicsScene(self)

        self.setScene(scene)

        item = OpenCVItem(cv2.imread("roi.jpg"))

        scene.addItem(item)


class Window(QtWidgets.QMainWindow):

    def __init__(self, parent=None):

        super(Window,self).__init__(parent=parent)

        self.setGeometry(1,31,900,900)

        self.setWindowTitle("Pre-Alignment system")


def run():

    app = QtWidgets.QApplication.instance()

    if app is None: 

        app = QtWidgets.QApplication(sys.argv)

    GUI = Window()

    view = Display_Pixels(GUI)

    GUI.setCentralWidget(view)

    GUI.show()

    sys.exit(app.exec_())


run()


查看完整回答
反对 回复 2021-11-09
  • 1 回答
  • 0 关注
  • 177 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信