title: Pyqt: custom frame doesn't detect mouse click under mouseMoveEvent
body: <p>I have created a custom Frame for a Qgraphicswidget. I have come across two problems, First, one being that clicks are not being detected under MouseMoveEvent, that is <code>event.button()</code> always returns 0 even if there is a mouse click. Second, is that my <code>setCursor()</code> doesn't change the cursor. Here is my code under the custom frame class.</p>
  <pre><code>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())
  </code></pre>
  <p>I have also tried using <code>eventfilter</code> but of no use.</p>
  <p>EDIT:</p>
  <pre><code>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 &gt; 0:
                  self.on_zoom_in()
  
              elif delta &lt; 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() &lt; 3.375:
              self.setTransformationAnchor(self.AnchorUnderMouse)
              self.scale(1.5, 1.5)
  
      def on_zoom_out(self):
  
          if self.transform().m11() &gt; 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())
  </code></pre>