无法在 Qgraphics 图像上绘制矩形

Not able to draw rectangel over Qgraphics image

我正在尝试在 Qgraphics 场景上绘制矩形。我找到了很多示例,但其中 none 个对我有用。该矩形绘制在 window 中未被 Qgraphics 视图小部件覆盖的区域,但是当我尝试图像时它不起作用。我不知道为什么。一项观察是 Qgraphicsview 鼠标释放事件没有被执行。但我无法解决问题。任何帮助都会有所帮助。提前致谢。

我正在使用的代码如下。

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'zoom_win_qt.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui
import numpy as np
from scipy.ndimage import zoom
import cv2
from matplotlib import pyplot as plt
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_zoom_win_qt(object):
    def setupUi(self, zoom_win_qt):
        zoom_win_qt.setObjectName(_fromUtf8("zoom_win_qt"))
        zoom_win_qt.resize(800, 600)
        self.centralwidget = QtGui.QWidget(zoom_win_qt)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.graphicsView = QtGui.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(80, 40, 611, 431))
        self.graphicsView.setObjectName(_fromUtf8("graphicsView"))        
        grview = self.graphicsView
        scene = QtGui.QGraphicsScene()
        pixmap = QtGui.QPixmap('Koala.jpg')
        pixmap = pixmap.scaledToHeight(420)
        scene.addPixmap(pixmap)        
        grview.setScene(scene)
        grview.show()        
        self.horizontalSlider = QtGui.QSlider(self.centralwidget)
        self.horizontalSlider.setGeometry(QtCore.QRect(80, 500, 160, 19))
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setObjectName(_fromUtf8("horizontalSlider"))
        self.progressBar = QtGui.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(590, 490, 118, 23))
        self.progressBar.setProperty("value", 24)
        self.progressBar.setObjectName(_fromUtf8("progressBar"))
        self.pushButton = QtGui.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(380, 500, 75, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))    

        self.pushButton.clicked.connect(test_clipped_zoom)  

        zoom_win_qt.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(zoom_win_qt)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        zoom_win_qt.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(zoom_win_qt)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        zoom_win_qt.setStatusBar(self.statusbar)

        self.retranslateUi(zoom_win_qt)
        QtCore.QMetaObject.connectSlotsByName(zoom_win_qt)

    def retranslateUi(self, zoom_win_qt):
        zoom_win_qt.setWindowTitle(_translate("zoom_win_qt", "MainWindow", None))
        self.pushButton.setText(_translate("zoom_win_qt", "PushButton", None))



class Myrect(QtGui.QMainWindow,Ui_zoom_win_qt):
    def __init__(self, *args, **kwargs):
        QtGui.QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)
        self.pos1 = [0,0]
        self.pos2 = [0,0]
        self.show()     


    def paintEvent(self, event):
        width = self.pos2[0]-self.pos1[0]
        height = self.pos2[1] - self.pos1[1]
        qp = QtGui.QPainter()        
        qp.begin(self)           
        qp.drawRect(self.pos1[0], self.pos1[1], width, height)        
        qp.end()

    def mousePressEvent(self, event):
        self.pos1[0], self.pos1[1] = event.pos().x(), event.pos().y()
        print("clicked")

    def mouseReleaseEvent(self, event):
        self.pos2[0], self.pos2[1] = event.pos().x(), event.pos().y()
        print("released")
        self.update()            






def test_clipped_zoom():
     zoom_win_qt.hide()
     w.show()




if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)

    w = Myrect()
    zoom_win_qt = QtGui.QMainWindow()
    ui = Ui_zoom_win_qt()
    ui.setupUi(zoom_win_qt)
    zoom_win_qt.show()




    sys.exit(app.exec_())

QGraphicsView是一个显示场景的widget(QGraphicsScene),所以常见的是在场景中添加一个矩形(就好像是一个演员),而不是绘制.您也在 Myrect 中绘画,这是其他小部件所在的小部件,因此它在背景中,其他小部件将覆盖您的绘画。

另一方面不建议修改Qt Designer生成的class,所以我冒昧地return将其恢复到初始状态

回到起点,添加一个矩形到QGraphicsScene你必须知道那些点在场景坐标系中的坐标,所以一种方法是使用eventFilter(),这里必须过滤GraphicsSceneMousePressGraphicsSceneMouseRelease事件,这些事件都有位置,我们可以使用scenePos()方法获取。

...
class Myrect(QtGui.QMainWindow,Ui_zoom_win_qt):
    def __init__(self, *args, **kwargs):
        QtGui.QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)   
        self.pushButton.clicked.connect(test_clipped_zoom)
        self.scene = QtGui.QGraphicsScene()
        pixmap = QtGui.QPixmap('Koala.jpg').scaledToHeight(420)
        self.scene.addPixmap(pixmap)        
        self.graphicsView.setScene(self.scene) 
        self.scene.installEventFilter(self)
        self.start = QtCore.QPointF()

    def eventFilter(self, obj, event):
        if obj == self.scene:
            if event.type() == QtCore.QEvent.GraphicsSceneMousePress:
                self.start = event.scenePos()
            elif event.type() == QtCore.QEvent.GraphicsSceneMouseRelease:
                end = event.scenePos()
                self.scene.addRect(QtCore.QRectF(self.start, end))
                self.start = QtCore.QPointF()
        return QtGui.QMainWindow.eventFilter(self, obj, event)


def test_clipped_zoom():
     zoom_win_qt.hide()
     w.show()

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    w = Myrect()
    w.show()
    sys.exit(app.exec_())

完整代码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'zoom_win_qt.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_zoom_win_qt(object):
    def setupUi(self, zoom_win_qt):
        zoom_win_qt.setObjectName(_fromUtf8("zoom_win_qt"))
        zoom_win_qt.resize(800, 600)
        self.centralwidget = QtGui.QWidget(zoom_win_qt)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.graphicsView = QtGui.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(80, 40, 611, 431))
        self.graphicsView.setObjectName(_fromUtf8("graphicsView"))             
        self.horizontalSlider = QtGui.QSlider(self.centralwidget)
        self.horizontalSlider.setGeometry(QtCore.QRect(80, 500, 160, 19))
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setObjectName(_fromUtf8("horizontalSlider"))
        self.progressBar = QtGui.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(590, 490, 118, 23))
        self.progressBar.setProperty("value", 24)
        self.progressBar.setObjectName(_fromUtf8("progressBar"))
        self.pushButton = QtGui.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(380, 500, 75, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))    
        zoom_win_qt.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(zoom_win_qt)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        zoom_win_qt.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(zoom_win_qt)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        zoom_win_qt.setStatusBar(self.statusbar)

        self.retranslateUi(zoom_win_qt)
        QtCore.QMetaObject.connectSlotsByName(zoom_win_qt)

    def retranslateUi(self, zoom_win_qt):
        zoom_win_qt.setWindowTitle(_translate("zoom_win_qt", "MainWindow", None))
        self.pushButton.setText(_translate("zoom_win_qt", "PushButton", None))



class Myrect(QtGui.QMainWindow,Ui_zoom_win_qt):
    def __init__(self, *args, **kwargs):
        QtGui.QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)   
        self.pushButton.clicked.connect(test_clipped_zoom)
        self.scene = QtGui.QGraphicsScene()
        pixmap = QtGui.QPixmap('Koala.jpg').scaledToHeight(420)
        self.scene.addPixmap(pixmap)        
        self.graphicsView.setScene(self.scene) 
        self.scene.installEventFilter(self)
        self.start = QtCore.QPointF()

    def eventFilter(self, obj, event):
        if obj == self.scene:
            if event.type() == QtCore.QEvent.GraphicsSceneMousePress:
                self.start = event.scenePos()
            elif event.type() == QtCore.QEvent.GraphicsSceneMouseRelease:
                end = event.scenePos()
                self.scene.addRect(QtCore.QRectF(self.start, end))
                self.start = QtCore.QPointF()
        return QtGui.QMainWindow.eventFilter(self, obj, event)


def test_clipped_zoom():
     zoom_win_qt.hide()
     w.show()

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    w = Myrect()
    w.show()
    sys.exit(app.exec_())