基本的想法是我不能在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
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()
还有主窗口的代码:
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()
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()