Python Pyqt:自定义帧不';在mouseMoveEvent下检测不到鼠标单击

Python Pyqt:自定义帧不';在mouseMoveEvent下检测不到鼠标单击,python,pyqt,pyqt5,Python,Pyqt,Pyqt5,我已经为Qgraphicswidget创建了一个自定义框架。我遇到了两个问题,首先,一个是在MouseMoveEvent下没有检测到单击,即event.button()即使有鼠标单击,也总是返回0。其次,我的setCursor()不会更改光标。这是我在自定义框架类下的代码 from PyQt5 import QtGui, QtCore from PyQt5.QtCore import Qt, QRectF, QEvent, QPoint from PyQt5.QtGui import QPen,

我已经为Qgraphicswidget创建了一个自定义框架。我遇到了两个问题,首先,一个是在MouseMoveEvent下没有检测到单击,即
event.button()
即使有鼠标单击,也总是返回0。其次,我的
setCursor()
不会更改光标。这是我在自定义框架类下的代码

from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import Qt, QRectF, QEvent, QPoint
from PyQt5.QtGui import QPen, QColor, QPainter, QBrush, qRgb, QPolygon
from PyQt5.QtWidgets import *
import sys


class Frame(QFrame):

    def __init__(self, parent=None, option=[], margin=0):
        super(Frame, self).__init__()

        self.parent = parent
        self._triangle = QPolygon()
        self.options = option
        self._margin = margin
        self.start_pos = None
        # self.parent.setViewport(parent)
        self.setStyleSheet('background-color: lightblue')
        self.setMouseTracking(True)
        self.installEventFilter(self)
        self.show()

    def update_option(self, option):
        self.options = option

    def paintEvent(self, event):
        super().paintEvent(event)

        qp = QPainter(self)

        qp.setPen(Qt.white)
        qp.setBrush(Qt.gray)
        qp.drawPolygon(self._triangle)

    def _recalculate_triangle(self):
        p = QPoint(self.width() - 20, self.height() - 10)
        q = QPoint(self.width() - 10, self.height() - 20)
        r = QPoint(self.width() - 10, self.height() - 10)

        self._triangle = QPolygon([p, q, r])
        self.update()

    def resizeEvent(self, event):
        self._recalculate_triangle()
        super().resizeEvent(event)

    def mousePressEvent(self, event):

        if event.button() == Qt.LeftButton:

            if event.button() == Qt.LeftButton and self._triangle.containsPoint(
                event.pos(), Qt.OddEvenFill
            ):
                self.parent.viewport().setCursor(Qt.SizeFDiagCursor)
                self.start_pos = event.pos()
                # print(self.start_pos)

            else:
                self.parent.viewport().unsetCursor()
                self.start_pos = None

        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):

        if self._triangle.containsPoint(event.pos(), Qt.OddEvenFill):
            self.parent.viewport().setCursor(Qt.SizeFDiagCursor)

        else:
            self.parent.viewport().unsetCursor()
            self.start_pos = None

        if event.button() == Qt.LeftButton:
            if event.button() == QtCore.Qt.LeftButton and self.start_pos is not None:
                self.parent.viewport().setCursor(Qt.SizeFDiagCursor)

                delta = event.pos() - self.start_pos

                self.n_resize(self.width()+delta.x(), self.height()+delta.y())
                self.start_pos = event.pos()

            elif not self._triangle.containsPoint(event.pos(), Qt.OddEvenFill):
                self.parent.viewport().unsetCursor()
                self.start_pos = None

        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        self.parent.viewport().unsetCursor()
        self.start_pos = None
        super().mouseReleaseEvent(event)

    def n_resize(self, width, height):
        self.resize(width, height)


if __name__ == '__main__':
    q = QApplication(sys.argv)
    a = Frame()
    sys.exit(q.exec())
我也尝试过使用
eventfilter
,但没有用

编辑:

从PyQt5导入QtGui,QtCore
从PyQt5.QtCore导入Qt,QPoint
从PyQt5.QtGui导入QPen、QColor、QPainter、QBrush、QPolygon
从PyQt5.QtWidgets导入*
导入系统
类图形布局(QGraphicsView):
def uuu init uuu(self,parent=None):
super()。\uuuu init\uuuu(父级)
self.scene=qgraphicscene()
self.lines=[]
self.draw_grid()
自身设置不透明度(0.3)
widget=QGraphicsProxyWidget()
t=堆栈(自身)
t、 setFlag(QGraphicsItem.ItemIsMovable)
t、 调整大小(340330)
self.scene.addItem(t)
self.setScene(self.scene)
self.show()
def创建_纹理(自):
image=QtGui.QImage(QtCore.QSize(30,30),QtGui.QImage.Format_RGBA64)
pen=QPen()
钢笔颜色(QColor(189190191))
笔设置宽度(2)
painter=QtGui.QPainter(图像)
画师:画笔
painter.drawRect(image.rect())
(完)
返回图像
def绘制网格(自):
纹理=自我。创建纹理()
brush=QBrush()
#brush.setColor(QColor('#999'))
笔刷。设置纹理图像(纹理)#网格图案。
self.scene.setBackgroundBrush(画笔)
borderColor=Qt.black
fillColor=QColor(“#DDD”)
def set_可见(自身,可见=真):
对于self.line中的行:
line.setVisible(可见)
def delete_网格(自):
对于self.line中的行:
self.scene.removietem(行)
del self.line[:]
def set_不透明度(自身,不透明度):
对于self.line中的行:
line.setOpacity(不透明度)
def wheelEvent(自我,事件):
如果event.modifiers()==Qt.ControlModifier:
delta=event.angleDelta().y()
如果增量>0:
self.on_zoom_in()
elif delta<0:
self.on\u缩放()
超级(图形布局,自我)。车轮事件(事件)
def鼠标压力事件(自身、事件):
如果event.button()==Qt.MidButton:
self.setCursor(Qt.OpenHandCursor)
self.mousepos=event.localPos()
super().mousePressEvent(事件)
def mouseMoveEvent(自身、事件):
#这有助于对整个区域进行平移
如果event.buttons()==Qt.MidButton:
delta=event.localPos()-self.mousepos
h=self.horizontalScrollBar().value()
v=self.verticalScrollBar().value()
self.horizontalScrollBar().setValue(int(h-delta.x()))
self.verticalScrollBar().setValue(int(v-delta.y()))
self.mousepos=event.localPos()
super().mouseMoveEvent(事件)
def mouseReleaseEvent(自身,事件):
self.cursor()
self.mousepos=event.localPos()
super().mouseReleaseEvent(事件)
放大时的def(自身):
如果self.transform().m11()<3.375:
self.setTransformationAnchor(self.AnchorUnderMouse)
自评量表(1.5,1.5)
def打开/缩小(自):
如果self.transform().m11()>0.7:
self.setTransformationAnchor(self.AnchorUnderMouse)
自刻度(1.0/1.5、1.0/1.5)
类堆栈(QGraphicsWidget):
_保证金=0
def uuu init uuu(self,parent=None):
super()。\uuuu init\uuuuu()
self.options=[]
self.gridlayout=parent
graphic_layout=QGraphicsLinearLayout(Qt.Vertical,self)
自宽,自高=10,10
self.outer_container=框架(父级、self.options、self._边距)
self.outer_container.setContentsMargins(0,0,0,0)
self.setParent(self.outer_容器)
layout=QVBoxLayout()
self.headerLayout=QGridLayout()
self.headerLayout.setContentsMargins(2,0,0,0)
self.top_bar=QFrame()
self.top_bar.setFrameShape(QFrame.StyledPanel)
自顶杆设置布局(自顶杆布局)
self.top_bar.setContentsMargins(0,0,0,0)
自顶杆设置最大高度(30)
#self.contentLayout=QVBoxLayout()
self.contentLayout=QFormLayout()
self.contentLayout.setContentsMargins(10,10,10,10)
self.contentLayout.setspace(5)
layout.addWidget(self.top_栏)
layout.addLayout(self.contentLayout)
布局。设置间距(0)
layout.setContentsMargins(0,0,0,0)
self.outer_container.setContentsMargins(0,0,0,0)
self.setContentsMargins(0,0,0,0)
self.setMaximumSize(400800)
self.outer_container.setLayout(布局)
widget=QGraphicsProxyWidget()
setWidget(self.outer_容器)
#todo:找到一种添加顶部工具栏小部件的方法
图形布局.附加项(小部件)
图形_布局设置间距(0)
图形布局。设置内容边缘(0,0,0,0)
#小部件移动和调整大小注意:不要触摸其中任何一个
self.\uuu mouseMovePos=无
自。_三角形=QPolygon()
self.start\u pos=无
def addHeaderWidget(self,widget=None,column=0,bg_color='green'):
self.top_bar.setStyleSheet(f'background-color:{bg_color};'))
self.headerLayout.addWidget(小部件,0,列)
类框架(QFrame):
定义初始化(self,父项=None,选项=[],边距=0):
超级(帧,自).\uuu初始化
self.parent=parent
自。_三角形=QPolygon()
self.options=选项
自身保证金=保证金
self.start\u pos=无
#self.parent.setViewport(父)
self.setStyleSheet('背景色:浅蓝色')
self.setMou
from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtGui import QPen, QColor, QPainter, QBrush, QPolygon
from PyQt5.QtWidgets import *
import sys



class graphLayout(QGraphicsView):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.scene = QGraphicsScene()
        self.lines = []
        self.draw_grid()
        self.set_opacity(0.3)

        widget = QGraphicsProxyWidget()

        t = stack(self)
        t.setFlag(QGraphicsItem.ItemIsMovable)
        t.resize(340, 330)

        self.scene.addItem(t)
        self.setScene(self.scene)
        self.show()

    def create_texture(self):
        image = QtGui.QImage(QtCore.QSize(30, 30), QtGui.QImage.Format_RGBA64)

        pen = QPen()
        pen.setColor(QColor(189, 190, 191))
        pen.setWidth(2)

        painter = QtGui.QPainter(image)
        painter.setPen(pen)
        painter.drawRect(image.rect())
        painter.end()

        return image

    def draw_grid(self):

        texture = self.create_texture()
        brush = QBrush()
        # brush.setColor(QColor('#999'))
        brush.setTextureImage(texture)  # Grid pattern.
        self.scene.setBackgroundBrush(brush)

        borderColor = Qt.black
        fillColor = QColor('#DDD')

    def set_visible(self, visible=True):
        for line in self.lines:
            line.setVisible(visible)

    def delete_grid(self):
        for line in self.lines:
            self.scene.removeItem(line)
        del self.lines[:]

    def set_opacity(self, opacity):
        for line in self.lines:
            line.setOpacity(opacity)

    def wheelEvent(self, event):

        if event.modifiers() == Qt.ControlModifier:

            delta = event.angleDelta().y()
            if delta > 0:
                self.on_zoom_in()

            elif delta < 0:
                self.on_zoom_out()

        super(graphLayout, self).wheelEvent(event)

    def mousePressEvent(self, event):

        if event.button() == Qt.MidButton:
            self.setCursor(Qt.OpenHandCursor)
            self.mousepos = event.localPos()

        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):


        # This helps to pan the area
        if event.buttons() == Qt.MidButton:
            delta = event.localPos() - self.mousepos
            h = self.horizontalScrollBar().value()
            v = self.verticalScrollBar().value()

            self.horizontalScrollBar().setValue(int(h - delta.x()))
            self.verticalScrollBar().setValue(int(v - delta.y()))

        self.mousepos = event.localPos()

        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):

        self.unsetCursor()
        self.mousepos = event.localPos()
        super().mouseReleaseEvent(event)

    def on_zoom_in(self):

        if self.transform().m11() < 3.375:
            self.setTransformationAnchor(self.AnchorUnderMouse)
            self.scale(1.5, 1.5)

    def on_zoom_out(self):

        if self.transform().m11() > 0.7:
            self.setTransformationAnchor(self.AnchorUnderMouse)
            self.scale(1.0 / 1.5, 1.0 / 1.5)


class stack(QGraphicsWidget):
    _margin = 0

    def __init__(self, parent=None):
        super().__init__()

        self.options = []
        self.gridlayout = parent

        graphic_layout = QGraphicsLinearLayout(Qt.Vertical, self)

        self.width, self.height = 10, 10

        self.outer_container = Frame(parent, self.options, self._margin)

        self.outer_container.setContentsMargins(0, 0, 0, 0)

        self.setParent(self.outer_container)

        layout = QVBoxLayout()
        self.headerLayout = QGridLayout()
        self.headerLayout.setContentsMargins(2, 0, 0, 0)

        self.top_bar = QFrame()
        self.top_bar.setFrameShape(QFrame.StyledPanel)
        self.top_bar.setLayout(self.headerLayout)
        self.top_bar.setContentsMargins(0, 0, 0, 0)
        self.top_bar.setMaximumHeight(30)

        # self.contentLayout = QVBoxLayout()
        self.contentLayout = QFormLayout()
        self.contentLayout.setContentsMargins(10, 10, 10, 10)
        self.contentLayout.setSpacing(5)

        layout.addWidget(self.top_bar)
        layout.addLayout(self.contentLayout)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        self.outer_container.setContentsMargins(0, 0, 0, 0)
        self.setContentsMargins(0, 0, 0, 0)

        self.setMaximumSize(400, 800)

        self.outer_container.setLayout(layout)

        widget = QGraphicsProxyWidget()
        widget.setWidget(self.outer_container)

        # todo: figure out a way to add top_bar widget
        graphic_layout.addItem(widget)
        graphic_layout.setSpacing(0)
        graphic_layout.setContentsMargins(0, 0, 0, 0)

        # widget move and resize note: don't touch any of these
        self.__mouseMovePos = None
        self._triangle = QPolygon()
        self.start_pos = None


    def addHeaderWidget(self, widget=None, column=0, bg_color='green'):
        self.top_bar.setStyleSheet(f'background-color:{bg_color};')
        self.headerLayout.addWidget(widget, 0, column)



class Frame(QFrame):

    def __init__(self, parent=None, option=[], margin=0):
        super(Frame, self).__init__()

        self.parent = parent
        self._triangle = QPolygon()
        self.options = option
        self._margin = margin
        self.start_pos = None
        # self.parent.setViewport(parent)
        self.setStyleSheet('background-color: lightblue')
        self.setMouseTracking(True)
        self.installEventFilter(self)
        self.show()

    def update_option(self, option):
        self.options = option

    def paintEvent(self, event):
        super().paintEvent(event)

        qp = QPainter(self)

        qp.setPen(Qt.white)
        qp.setBrush(Qt.gray)
        qp.drawPolygon(self._triangle)

    def _recalculate_triangle(self):
        p = QPoint(self.width() - 20, self.height() - 10)
        q = QPoint(self.width() - 10, self.height() - 20)
        r = QPoint(self.width() - 10, self.height() - 10)

        self._triangle = QPolygon([p, q, r])
        self.update()

    def resizeEvent(self, event):
        self._recalculate_triangle()
        super().resizeEvent(event)

    def mousePressEvent(self, event):

        if event.button() == Qt.LeftButton:

            if event.button() == Qt.LeftButton and self._triangle.containsPoint(
                event.pos(), Qt.OddEvenFill
            ):
                self.parent.viewport().setCursor(Qt.SizeFDiagCursor)
                self.start_pos = event.pos()
                # print(self.start_pos)

            else:
                self.parent.viewport().unsetCursor()
                self.start_pos = None

        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):

        if self._triangle.containsPoint(event.pos(), Qt.OddEvenFill):
            self.parent.viewport().setCursor(Qt.SizeFDiagCursor)

        else:
            self.parent.viewport().unsetCursor()
            self.start_pos = None

        if event.button() == Qt.LeftButton:
            if event.button() == QtCore.Qt.LeftButton and self.start_pos is not None:
                self.parent.viewport().setCursor(Qt.SizeFDiagCursor)

                delta = event.pos() - self.start_pos

                self.n_resize(self.width()+delta.x(), self.height()+delta.y())
                self.start_pos = event.pos()

            elif not self._triangle.containsPoint(event.pos(), Qt.OddEvenFill):
                self.parent.viewport().unsetCursor()
                self.start_pos = None

        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        self.parent.viewport().unsetCursor()
        self.start_pos = None
        super().mouseReleaseEvent(event)

    def n_resize(self, width, height):
        self.resize(width, height)


if __name__ == '__main__':
    q = QApplication(sys.argv)
    a = graphLayout()
    sys.exit(q.exec())
from PyQt5 import QtCore, QtGui, QtWidgets

class SizeGrip(QtWidgets.QSizeGrip):
    def __init__(self, parent):
        super().__init__(parent)
        parent.installEventFilter(self)
        self.setFixedSize(30, 30)
        self.polygon = QtGui.QPolygon([
            QtCore.QPoint(10, 20), 
            QtCore.QPoint(20, 10), 
            QtCore.QPoint(20, 20), 
        ])

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.Resize:
            geo = self.rect()
            geo.moveBottomRight(source.rect().bottomRight())
            self.setGeometry(geo)
        return super().eventFilter(source, event)

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setPen(QtCore.Qt.white)
        qp.setBrush(QtCore.Qt.gray)
        qp.drawPolygon(self.polygon)


class Container(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.sizeGrip = SizeGrip(self)
        self.startPos = None
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(6, 6, 6, 30)
        self.setStyleSheet('''
            Container {
                background: lightblue;
                border: 0px;
                border-radius: 4px;
            }
        ''')

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.startPos = event.pos()

    def mouseMoveEvent(self, event):
        if self.startPos:
            self.move(self.pos() + (event.pos() - self.startPos))

    def mouseReleaseEvent(self, event):
        self.startPos = None


class GraphicsRoundedFrame(QtWidgets.QGraphicsProxyWidget):
    def __init__(self):
        super().__init__()
        self.container = Container()
        self.setWidget(self.container)

    def addWidget(self, widget):
        self.container.layout().addWidget(widget)

    def paint(self, qp, opt, widget):
        qp.save()
        p = QtGui.QPainterPath()
        p.addRoundedRect(self.boundingRect().adjusted(0, 0, -.5, -.5), 4, 4)
        qp.setClipPath(p)
        super().paint(qp, opt, widget)
        qp.restore()


class View(QtWidgets.QGraphicsView):
    def __init__(self):
        super().__init__()
        scene = QtWidgets.QGraphicsScene()
        self.setScene(scene)
        self.setRenderHints(QtGui.QPainter.Antialiasing)
        scene.setSceneRect(0, 0, 1024, 768)

        texture = QtGui.QImage(30, 30, QtGui.QImage.Format_ARGB32)
        qp = QtGui.QPainter(texture)
        qp.setBrush(QtCore.Qt.white)
        qp.setPen(QtGui.QPen(QtGui.QColor(189, 190, 191), 2))
        qp.drawRect(texture.rect())
        qp.end()
        scene.setBackgroundBrush(QtGui.QBrush(texture))

        testFrame = GraphicsRoundedFrame()
        scene.addItem(testFrame)

        testFrame.addWidget(QtWidgets.QLabel('I am a label'))
        testFrame.addWidget(QtWidgets.QPushButton('I am a button'))

import sys
app = QtWidgets.QApplication(sys.argv)
w = View()
w.show()
sys.exit(app.exec_())