Python Pyqt:自定义帧不';在mouseMoveEvent下检测不到鼠标单击
我已经为Qgraphicswidget创建了一个自定义框架。我遇到了两个问题,首先,一个是在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,
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_())