- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在图形场景中有用户可调整的注释。注释的大小/旋转通过拖动注释周围矩形的角来处理。我使用自定义矩形(而不是boundingRect),因此它遵循父注释的旋转。控制角由两个椭圆标记,其父级是矩形,因此矩形/椭圆/注释的转换是无缝的。
我想检测光标何时位于某个角上、它是哪个角以及确切的坐标。对于此任务,我似乎应该使用 sceneEventFilter 过滤带有父矩形的悬停事件。
我尝试了无数种实现 sceneEventFilter 的方法,但没有成功。所有事件都直接进入hoverEnterEvent函数。我只找到了一些执行类似操作的示例代码,但我只是卡住了。顺便说一句,过去 3 个月我完全自学了 Python 和 QT,所以请耐心等待。我确信我错过了一些非常基本的东西。该代码是一个带有两个省略号的简化 GUI。我们希望捕获 sceneEventFilter 中的事件,但总是转到hoverEnterEvent。
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsItem
import sys
class myHandle(QtGui.QGraphicsEllipseItem):
def __init__(self, parent = None):
super(myHandle, self).__init__(parent)
def addTheHandle(self, h_parent = 'null', kind = 'null'):
handle_w = 40
if kind == 'scaling handle':
handle_x = h_parent.boundingRect().topRight().x() - handle_w/2
handle_y = h_parent.boundingRect().topRight().y() - handle_w/2
if kind == 'rotation handle':
handle_x = h_parent.boundingRect().topLeft().x() - handle_w/2
handle_y = h_parent.boundingRect().topLeft().y() - handle_w/2
the_handle = QtGui.QGraphicsEllipseItem(QtCore.QRectF(handle_x, handle_y, handle_w, handle_w))
the_handle.setPen(QtGui.QPen(QtGui.QColor(255, 100, 0), 3))
the_handle.setParentItem(h_parent)
the_handle.setAcceptHoverEvents(True)
the_handle.kind = kind
return the_handle
class myRect(QtGui.QGraphicsRectItem):
def __init__(self, parent = None):
super(myRect, self).__init__(parent)
def rectThing(self, boundingrectangle):
self.setAcceptHoverEvents(True)
self.setRect(boundingrectangle)
mh = myHandle()
rotation_handle = mh.addTheHandle(h_parent = self, kind = 'rotation handle')
scaling_handle = mh.addTheHandle(h_parent = self, kind = 'scaling handle')
self.installSceneEventFilter(rotation_handle)
self.installSceneEventFilter(scaling_handle)
return self, rotation_handle, scaling_handle
def sceneEventFilter(self, event):
print('scene ev filter')
return False
def hoverEnterEvent(self, event):
print('hover enter event')
class Basic(QtGui.QMainWindow):
def __init__(self):
super(Basic, self).__init__()
self.initUI()
def eventFilter(self, source, event):
return QtGui.QMainWindow.eventFilter(self, source, event)
def exit_the_program(self):
pg.exit()
def initUI(self):
self.resize(300, 300)
self.centralwidget = QtGui.QWidget()
self.setCentralWidget(self.centralwidget)
self.h_layout = QtGui.QHBoxLayout(self.centralwidget)
self.exit_program = QtGui.QPushButton('Exit')
self.exit_program.clicked.connect(self.exit_the_program)
self.h_layout.addWidget(self.exit_program)
self.this_scene = QGraphicsScene()
self.this_view = QGraphicsView(self.this_scene)
self.this_view.setMouseTracking(True)
self.this_view.viewport().installEventFilter(self)
self.h_layout.addWidget(self.this_view)
self.circle = self.this_scene.addEllipse(QtCore.QRectF(40, 40, 65, 65), QtGui.QPen(QtCore.Qt.black))
mr = myRect()
the_rect, rotation_handle, scaling_handle = mr.rectThing(self.circle.boundingRect())
the_rect.setPen(QtGui.QPen(QtCore.Qt.black))
the_rect.setParentItem(self.circle)
self.this_scene.addItem(the_rect)
self.this_scene.addItem(rotation_handle)
self.this_scene.addItem(scaling_handle)
def main():
app = QtGui.QApplication([])
main = Basic()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
最佳答案
主要问题是您正在矩形上安装目标项的事件过滤器:矩形的事件过滤器永远不会接收任何内容。此外,sceneEventFilter
接受两个参数(监视的项目和事件),但您只使用了一个。
您应该做的是将矩形的事件过滤器安装在目标项上:
rotation_handle.installSceneEventFilter(self)
scaling_handle.installSceneEventFilter(self)
也就是说,如果您想使用这些椭圆项来缩放或旋转源圆,那么您的方法一开始就有点错误。
from math import sqrt
# ...
class myRect(QtGui.QGraphicsRectItem):
def __init__(self, parent):
super(myRect, self).__init__(parent)
self.setRect(parent.boundingRect())
# rotation is usually based on the center of an object
self.parentItem().setTransformOriginPoint(self.parentItem().rect().center())
# a rectangle that has a center at (0, 0)
handleRect = QtCore.QRectF(-20, -20, 40, 40)
self.rotation_handle = QtGui.QGraphicsEllipseItem(handleRect, self)
self.scaling_handle = QtGui.QGraphicsEllipseItem(handleRect, self)
# position the handles by centering them at the right corners
self.rotation_handle.setPos(self.rect().topLeft())
self.scaling_handle.setPos(self.rect().topRight())
for source in (self.rotation_handle, self.scaling_handle):
# install the *self* event filter on the handles
source.installSceneEventFilter(self)
source.setPen(QtGui.QPen(QtGui.QColor(255, 100, 0), 3))
def sceneEventFilter(self, source, event):
if event.type() == QtCore.QEvent.GraphicsSceneMouseMove:
# map the handle event position to the ellipse parent item; we could
# also map to "self", but using the parent is more consistent
localPos = self.parentItem().mapFromItem(source, event.pos())
if source == self.rotation_handle:
# create a temporary line to get the rotation angle
line = QtCore.QLineF(self.boundingRect().center(), localPos)
# add the current rotation to the angle between the center and the
# top left corner, then subtract the new line angle
self.parentItem().setRotation(135 + self.parentItem().rotation() - line.angle())
# note that I'm assuming that the ellipse is a circle, so the top
# left angle will always be at 135°; if it's not a circle, the
# rect width and height won't match and the angle will be
# different, so you'll need to compute that
# parentRect = self.parentItem().rect()
# oldLine = QtCore.QLineF(parentRect.center(), parentRect.topLeft())
# self.parentItem().setRotation(
# oldLine.angle() + self.parentItem().rotation() - line.angle())
elif source == self.scaling_handle:
# still assuming a perfect circle, so the rectangle is a square;
# the line from the center to the top right corner is used to
# compute the square side size, which is the double of a
# right-triangle cathetus where the hypotenuse is the line
# between the center and any of its corners;
# if the ellipse is not a perfect circle, you'll have to
# compute both of the catheti
hyp = QtCore.QLineF(self.boundingRect().center(), localPos)
size = sqrt(2) * hyp.length()
rect = QtCore.QRectF(0, 0, size, size)
rect.moveCenter(self.rect().center())
self.parentItem().setRect(rect)
self.setRect(rect)
# update the positions of both handles
self.rotation_handle.setPos(self.rect().topLeft())
self.scaling_handle.setPos(self.rect().topRight())
return True
elif event.type() == QtCore.QEvent.GraphicsSceneMousePress:
# return True to the press event (which is almost as setting it as
# accepted, so that it won't be processed further more by the scene,
# allowing the sceneEventFilter to capture the following mouseMove
# events that the watched graphics items will receive
return True
return super(myRect, self).sceneEventFilter(source, event)
class Basic(QtGui.QMainWindow):
# ...
def initUI(self):
# ...
self.circle = self.this_scene.addEllipse(QtCore.QRectF(40, 40, 65, 65), QtGui.QPen(QtCore.Qt.black))
mr = myRect(self.circle)
self.this_scene.addItem(mr)
关于python - 在pyqt中使用sceneEventFilter捕获悬停事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59243514/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!