在鼠标事件类之外读取或传递数据

时间:2018-10-18 06:44:34

标签: python pyqt4

我有一个使用橡皮筋选择图像上区域的小部件,可以在任何方面进行编辑。我需要添加一些功能,一旦放置橡皮筋,它就可以重新调整大小或进行编辑,因此我的想法是在鼠标释放事件后保存区域点(x,y,w,h)。

但是现在的问题是,如何在橡皮筋类之外传递鼠标释放事件中读取的数据。

这是我对橡皮筋的拖动和编辑代码。

class rubberBandWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.tweaking = False
        self.tweakingpart = ""

    def mousePressEvent(self, event):
        pt = self.mapFromGlobal(event.globalPos())
        rg = self.rubberBand.geometry()

        if rg.isValid():
            tl, tr, bl, br = rg.topLeft(), rg.topRight(), rg.bottomLeft(), rg.bottomRight()
            off, offx, offy = QPoint(3, 3), QPoint(4, -3), QPoint(-3, 4)

            if QRect(tl - off, tl + off).contains(pt):
                self.tweakingpart = "topLeft";
                self.setCursor(Qt.SizeFDiagCursor)
            elif QRect(tr - off, tr + off).contains(pt):
                self.tweakingpart = "topRight";
                self.setCursor(Qt.SizeBDiagCursor)
            elif QRect(bl - off, bl + off).contains(pt):
                self.tweakingpart = "bottomLeft";
                self.setCursor(Qt.SizeBDiagCursor)
            elif QRect(br - off, br + off).contains(pt):
                self.tweakingpart = "bottomRight";
                self.setCursor(Qt.SizeFDiagCursor)
            elif QRect(tl + offx, tr - offx).contains(pt):
                self.tweakingpart = "top";
                self.setCursor(Qt.SizeVerCursor)
            elif QRect(bl + offx, br - offx).contains(pt):
                self.tweakingpart = "bottom"
                self.setCursor(Qt.SizeVerCursor)
            elif QRect(tl + offy, bl - offy).contains(pt):
                self.tweakingpart = "left";
                self.setCursor(Qt.SizeHorCursor)
            elif QRect(tr + offy, br - offy).contains(pt):
                self.tweakingpart = "right";
                self.setCursor(Qt.SizeHorCursor)

            if self.tweakingpart != "":
                self.tweaking = True
                return

        self.origin = pt
        self.rubberBand.setGeometry(QRect(self.origin, QtCore.QSize()))
        self.rubberBand.show()

    def mouseMoveEvent(self, event):
        pt = self.mapFromGlobal(event.globalPos())
        if self.tweaking:
            rg = self.rubberBand.geometry()
            if self.tweakingpart == "topLeft":
                rg.setTopLeft(pt)
            elif self.tweakingpart == "topRight":
                rg.setTopRight(pt)
            elif self.tweakingpart == "bottomLeft":
                rg.setBottomLeft(pt)
            elif self.tweakingpart == "bottomRight":
                rg.setBottomRight(pt)
            elif self.tweakingpart == "top":
                rg.setTop(pt.y())
            elif self.tweakingpart == "bottom":
                rg.setBottom(pt.y())
            elif self.tweakingpart == "left":
                rg.setLeft(pt.x())
            elif self.tweakingpart == "right":
                rg.setRight(pt.x())
            self.rubberBand.setGeometry(rg)
        else:
            self.rubberBand.setGeometry(QRect(self.origin, pt).normalized())

这是我有关释放事件的代码,以及需要在类外传递或读取的(x,y,w,h)数据。

def mouseReleaseEvent(self, event):
    self.tweaking = False
    self.tweakingpart = ""
    self.unsetCursor()

    if self.rubberBand.width() != 0 and self.rubberBand.height() != 0:
        print(self.rubberBand.x(), self.rubberBand.y(), self.rubberBand.width(), self.rubberBand.height())

每次释放鼠标时我都需要数据并保存。因此,一旦用户需要重新调整大小并进行编辑,我的想法是设置橡皮筋的几何形状并重新运行该类,以便可以再次对其进行编辑。

1 个答案:

答案 0 :(得分:0)

如果要在类之外公开数据,则应使用如下所示的信号:

import sys

from PyQt4 import QtCore, QtGui

class rubberBandWidget(QtGui.QWidget):
    rectChanged = QtCore.pyqtSignal(QtCore.QRect) # create signal
    ...
    def mouseReleaseEvent(self, event):
        self.tweaking = False
        self.tweakingpart = ""
        self.unsetCursor()

        if not self.rubberBand.geometry().isNull():
            self.rectChanged.emit(self.rubberBand.geometry()) # emit signal


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    w = rubberBandWidget()
    def on_rectChanged(rect):
        # receiver
        print(rect.x(), rect.y(), rect.width(), rect.height())
    w.rectChanged.connect(on_rectChanged) # connect signal
    w.show()
    sys.exit(app.exec_())

另一方面,我看到您的代码非常耦合,因为如果您想在另一个小部件中使用相同的功能,则必须复制所有代码,这是不希望的,因此,我花时间创建了一个自定义QRubberband具有该功能,在下一部分中,我将显示一个示例。

import sys

from PyQt4 import QtCore, QtGui


class RubberBand(QtGui.QRubberBand):
    rectChanged = QtCore.pyqtSignal(QtCore.QRect)

    TopLeft, TopRight, BottomLeft, BottomRight, Top, Bottom, Left, Right, NonePos = range(9)

    def __init__(self, parent=None):
        super(RubberBand, self).__init__(QtGui.QRubberBand.Rectangle, parent)
        self._widget = None
        self.setWidget(parent)
        self.tweakingpart = RubberBand.NonePos

        self.cursors = [QtCore.Qt.SizeFDiagCursor,
                        QtCore.Qt.SizeBDiagCursor,
                        QtCore.Qt.SizeBDiagCursor,
                        QtCore.Qt.SizeFDiagCursor,
                        QtCore.Qt.SizeVerCursor,
                        QtCore.Qt.SizeVerCursor,
                        QtCore.Qt.SizeHorCursor,
                        QtCore.Qt.SizeHorCursor]

    def setWidget(self, widget):
        if widget is None:
            return
        if self._widget is not None:
            self._widget.removeEventFilter(self)
        self._widget = widget
        self._widget.installEventFilter(self)
        self.setParent(widget)

    def eventFilter(self, obj, event):
        if self._widget is obj:
            if event.type() == QtCore.QEvent.MouseButtonPress:
                self.handleMousePressEvent(event.pos())
                return True
            elif event.type() == QtCore.QEvent.MouseMove:
                self.handleMouseMoveEvent(event.pos())
                return True
            elif event.type() == QtCore.QEvent.MouseButtonRelease:
                self.handleMouseReleaseEvent(event.pos())
                return True
        return super(RubberBand, self).eventFilter(obj, event)

    def handleMousePressEvent(self, pt):
        rg = self.geometry()
        if not rg.isValid():
            return
        off, offx, offy = QtCore.QPoint(3, 3), QtCore.QPoint(4, -3), QtCore.QPoint(-3, 4)
        rect = QtCore.QRect(-off, off)
        tl, tr, bl, br = rg.topLeft(), rg.topRight(), rg.bottomLeft(), rg.bottomRight()
        for i, coord in enumerate([tl, tr, bl, br]):
            rect.moveCenter(coord)
            if rect.contains(pt):
                self.tweakingpart = i
        if QtCore.QRect(tl + offx, tr - offx).contains(pt):
            self.tweakingpart = RubberBand.Top
        elif QtCore.QRect(bl + offx, br - offx).contains(pt):
            self.tweakingpart = RubberBand.Bottom
        elif QtCore.QRect(tl + offy, bl - offy).contains(pt):
            self.tweakingpart = RubberBand.Left
        elif QtCore.QRect(tr + offy, br - offy).contains(pt):
                self.tweakingpart = RubberBand.Right

        if 0 <= self.tweakingpart < RubberBand.NonePos:
            self._widget.setCursor(self.cursors[self.tweakingpart])
            return
        self.setGeometry(QtCore.QRect(pt, QtCore.QSize()))
        self.show()

    def handleMouseMoveEvent(self, pt):
        rg = self.geometry()
        if 0 <= self.tweakingpart < RubberBand.NonePos:
            if self.tweakingpart == RubberBand.TopLeft:
                rg.setTopLeft(pt)
            elif self.tweakingpart == RubberBand.TopRight:
                rg.setTopRight(pt)
            elif self.tweakingpart == RubberBand.BottomLeft:
                rg.setBottomLeft(pt)
            elif self.tweakingpart == RubberBand.BottomRight:
                rg.setBottomRight(pt)
            elif self.tweakingpart == RubberBand.Top:
                rg.setTop(pt.y())
            elif self.tweakingpart == RubberBand.Bottom:
                rg.setBottom(pt.y())
            elif self.tweakingpart == RubberBand.Left:
                rg.setLeft(pt.x())
            elif self.tweakingpart == RubberBand.Right:
                rg.setRight(pt.x())
        else:
            rg = QtCore.QRect(rg.topLeft(), pt).normalized()
        self.setGeometry(rg)

    def handleMouseReleaseEvent(self, pt):
        self.tweakingpart = RubberBand.NonePos
        self._widget.unsetCursor()
        if not self.geometry().isNull():
            self.rectChanged.emit(self.geometry())


class TestWidget(QtGui.QWidget):
    pass


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    w = TestWidget()
    rubberBand = RubberBand(w)
    def on_rectChanged(rect):
        print(rect.x(), rect.y(), rect.width(), rect.height())
    rubberBand.rectChanged.connect(on_rectChanged)
    w.show()
    sys.exit(app.exec_())