Reputation: 1619
The basic idea is that I can't use a QGraphicsView class to draw while inside a QMainWindow. I can see the painEvent firing and that the information is flowing to the method that performs the drawing, but in the end nothing gets displayed. Here is the Class with the 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
qp.setBrush(QColor(r, g, b))
qp.drawRect(x, y, w, w)
else:
qp.setBrush(QColor(r, g, b))
qp.drawRect(x, y, w, w)
#qp.setBrush(QColor(200, 0, 0))
#qp.drawRect(x, y, w, w)
x = x + w # move right
y = y + w # move down
x = 0 # rest to left edge
def mousePressEvent(self, QMouseEvent):
w = 16.0
#print("MOUSE:")
#print('(', int(QMouseEvent.x()/w), ', ', int(QMouseEvent.y()/w), ')')
#print (QMouseEvent.pos())
x = float(QMouseEvent.x())
y = float(QMouseEvent.y())
self.grid[int(y/w)][int(x/w)] = -1 * self.grid[int(y/w)][int(x/w)]
#print(img[int(y/w), int(x/w), :])
self.repaint()
#self.update()
And also the code for the main window:
class Window(QMainWindow):
def __init__(self, parent=None):
#This initializes the main window or form
super(Window,self).__init__(parent=parent)
self.setGeometry(1,31,900,900)
self.setWindowTitle("Pre-Alignment system")
def run():
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
GUI = Window()
view = Display_Pixels(GUI)
#view = MyView(GUI)
GUI.show()
sys.exit(app.exec_())
run()
Upvotes: 1
Views: 878
Reputation: 243887
QGraphicsView inherits from QAbstractScrollArea so the QPainter must set in the viewport()
, that is:
def paintEvent(self, e):
qp = QPainter()
qp.begin(self.viewport())
self.drawRectangles(qp)
qp.end()
Although I would paint it is not the best since QGraphicsView has a paint layer that uses the items. In this case it is best to implement a custom item, also I have improved your algorithm.:
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()
Upvotes: 3