- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了一个基于 QWidget
的 ImageView
小部件,其中包含一个 QGraphicsView
。该小部件显示图像,并允许您通过 QGraphicsRectItem 用鼠标绘制 ROI(感兴趣区域)。ImageView 小部件运行良好,但如果拖动 ROI 矩形并且您想在其他位置重绘它,则鼠标事件捕获的位置无法正确映射到场景。
这里有一些图片来解释我的意思。
包含 ImageView 小部件的对话框,其操作控制小部件本身:
如果启用选择,您可以绘制一个矩形:
注意矩形右下角的指针位置。 ROI 只能在图像内部绘制。
如果禁用选择,您可以拖动之前绘制的矩形:
此后,如果启用选择并且您想要重绘矩形:
指针位置被捕获得很好(这是事实!),正如您在对话框状态栏上看到的那样,但是这个位置(用于设置矩形几何形状)不再对应于矩形位置。
我对 Qt 还很陌生,代码如下:
class ImageView(QtGui.QWidget):
scaleChanged = QtCore.pyqtSignal()
statusChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(ImageView, self).__init__(parent)
self.scale_factor = 0.0
# Imagen
self.image_item = QtGui.QGraphicsPixmapItem()
# ROI
self.ROI_item = FancyQGraphicsRectItem(self.image_item)
self.ROI_item.setFlag(self.ROI_item.ItemIsMovable)
self.ROI_item.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
self.ROI_item.setPen(QtGui.QPen(QtCore.Qt.white, 0, QtCore.Qt.DashDotLine))
self.ROI_item.setCursor(QtCore.Qt.OpenHandCursor)
self.ROI_added = False
# Escena
self.scene = QtGui.QGraphicsScene()
# Vista
self.view = FancyQGraphicsView()
self.view.ROI_item = self.ROI_item
self.view.statusChanged.connect(self.change_status)
self.view.setScene(self.scene)
self.view.setBackgroundRole(QtGui.QPalette.Dark)
self.view.setAlignment(QtCore.Qt.AlignCenter)
self.view.setFrameShape(QtGui.QFrame.NoFrame)
self.view.setRenderHint(QtGui.QPainter.Antialiasing, False)
self.view.setMouseTracking(True)
# Disposición
layout = QtGui.QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.view)
self.setLayout(layout)
def setImage(self, pixmap):
self.image_item.setPixmap(pixmap)
self.scene.addItem(self.image_item)
self.scene.setSceneRect(0, 0, self.image_item.boundingRect().right(), self.image_item.boundingRect().bottom())
self.view.setSceneSize()
def selectionEnable(self, value):
self.view.selectionEnable(value)
if value:
self.ROI_item.setCursor(QtCore.Qt.CrossCursor)
self.view.setInteractive(False)
self.view.viewport().setCursor(QtCore.Qt.CrossCursor)
if not self.ROI_added:
self.ROI_added = True
else:
self.view.viewport().setCursor(QtCore.Qt.ArrowCursor)
self.ROI_item.setCursor(QtCore.Qt.OpenHandCursor)
self.view.setInteractive(True)
def setupDrag(self, value):
if value:
self.view.setInteractive(False)
self.view.setDragMode(self.view.ScrollHandDrag)
else:
self.view.setDragMode(self.view.NoDrag)
self.view.setInteractive(True)
def normal_size(self):
if self.scale_factor != 1.0:
self.view.resetMatrix()
self.scale_factor = 1.0
self.scaleChanged.emit()
def scale_image(self, factor):
self.scale_factor *= factor
self.view.scale(factor, factor)
self.scaleChanged.emit()
def delete_roi(self):
self.ROI_item.setRect(0, 0, 0, 0)
@QtCore.pyqtSlot(str)
def change_status(self, message):
self.statusChanged.emit(message)
class FancyQGraphicsView(QtGui.QGraphicsView):
statusChanged = QtCore.pyqtSignal(str)
scene_size = (0, 0)
ROI_item = None
event_origin = None
selection = False
click = False
def mousePressEvent(self, event):
if self.selection:
event_pos = self.mapToScene(event.pos())
pos = (int(event_pos.x()), int(event_pos.y()))
if 0 <= pos[0] < self.scene_size[0] and 0 <= pos[1] < self.scene_size[1]:
self.event_origin = event_pos
else:
self.event_origin = None
self.click = True
else:
QtGui.QGraphicsView.mousePressEvent(self, event)
def mouseMoveEvent(self, event):
event_pos = self.mapToScene(event.pos())
if self.selection and self.click:
if self.event_origin:
self.statusChanged.emit("x1: {0:>5d} y1: {1:>5d} "
"x2: {2:>5d} y2: {3:>5d}".format(int(self.event_origin.x()),
int(self.event_origin.y()),
int(event_pos.x()),
int(event_pos.y())))
if event_pos.x() < 0:
event_pos.setX(0)
elif event_pos.x() > self.scene_size[0] - 1:
event_pos.setX(self.scene_size[0] - 1)
if event_pos.y() < 0:
event_pos.setY(0)
elif event_pos.y() > self.scene_size[1] - 1:
event_pos.setY(self.scene_size[1] - 1)
self.ROI_item.setRect(QtCore.QRectF(self.event_origin, event_pos).normalized())
print self.ROI_item.rect(), self.event_origin, event_pos
else:
self.statusChanged.emit("x: {0:>5d} y: {1:>5d}".format(int(event_pos.x()), int(event_pos.y())))
else:
self.statusChanged.emit("x: {0:>5d} y: {1:>5d}".format(int(event_pos.x()), int(event_pos.y())))
QtGui.QGraphicsView.mouseMoveEvent(self, event)
def mouseReleaseEvent(self, event):
if self.selection:
self.click = False
if self.event_origin:
self.event_origin = None
else:
QtGui.QGraphicsView.mouseReleaseEvent(self, event)
def selectionEnable(self, value):
self.selection = value
def setSceneSize(self):
rect = self.scene().sceneRect()
self.scene_size = (rect.width(), rect.height())
class FancyQGraphicsRectItem(QtGui.QGraphicsRectItem):
def mousePressEvent(self, event):
self.setCursor(QtCore.Qt.ClosedHandCursor)
QtGui.QGraphicsRectItem.mousePressEvent(self, event)
def mouseMoveEvent(self, event):
QtGui.QGraphicsRectItem.mouseMoveEvent(self, event)
# Maybe this could be modified
def mouseReleaseEvent(self, event):
self.setCursor(QtCore.Qt.OpenHandCursor)
QtGui.QGraphicsRectItem.mouseReleaseEvent(self, event)
为什么会发生这种情况?以前,我尝试在矩形的图像中实现受限的可移动区域,但该项目在拖动时无法正确识别其在场景中的位置。
最佳答案
您的问题是由于您使用QGraphicsRectItem
的方式造成的。当您最初正确设置矩形时,该项目最初放置在场景的坐标 (0,0)
处。因此,QGraphicsRectItem
从 (0,0)
延伸到矩形的右下角坐标(在场景坐标中)。
当您移动 ROI 时,您将平移整个项目,而不仅仅是项目内的矩形。这意味着该项目不再位于 (0,0)
,因此您输入的坐标会发生偏移,因为您使用的是场景坐标而不是项目坐标。
有多种方法(例如QGraphicsItem.mapFromScene()
)可以将坐标转换为正确的引用点(请注意,这应该考虑到您的 ROI 是 ROI 的子级) self.image_item
以及如果它从 (0,0)
移开的话。
另一种选择是,您可以将 ROI 重新定位到初始单击坐标,然后根据初始单击坐标和当前单击坐标之间的差异调整其大小。所以在 mouseMoveEvent
中你可以这样做:
self.ROI_item.setPos(self.event_origin)
self.ROI_item.setRect(QtCore.QRectF(QtCore.QPointF(0,0), event_pos-self.event_origin).normalized())
但是,我怀疑如果移动父项,或者对 QGraphicsView
应用缩放,则可能会中断。在这种情况下,您可能需要使用 QGraphicsItem.mapFromScene()
方法进行研究(尽管始终将项目重新定位到初始单击位置可能很有用,如果只是为了缩小边界框)的项目)
关于python - PyQt4 - 拖动后 QGraphicsItem 位置未正确映射到场景中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32018223/
websocket的用途/场景 先总结:高即时性服务,比如聊天室的群聊,server顺序收到了张三,李四的消息,立即就推送给王五,不能让王五等半天。 Ajax也可以一秒一刷,让王五去问张三说话没,如果
前端的工作过程里,本地开发、提供测试环境,总得有个用着顺手的服务器软件,这个场景里nginx很流行。 介绍两个好用的配置项:rewrite try_files @xxxx rewrite 比较
我有一个场景的两个不同角度的 2 个视频文件,我想重建场景的 3D 估计。它类似于 3D 传感器的作用(例如 Kinect、PrimeSense)。我正在寻找一个库,甚至是一个完善的机器视觉算法,以便
我已阅读RebaseProject页面并尝试了一个不平凡的例子(不是对一个完整的分支进行 rebase )。这与 rebase D 的情况类似我场景B。 这是rebase之前的情况: default
有没有办法将我的场景保存在 JavaFx 应用程序中单独的 Java 文件中?我尝试过这样的事情: public class MyApp extends Application { pri
我有这样的场景:用户想要查看大量有关自己的信息。例如:年龄、姓名、地位、收入、工作、爱好、 child 的名字、妻子的名字、酋长的名字、祖父/祖母的名字。大约 50 个变量。他可以选择任何变量来显示信
我希望有人能帮助我解决这个问题:我有一个包含条目的表。我想执行查询并根据模式获取得分最高的记录。模式将是:如果我的话按原样出现,那么该条目的分数将是最高的。如果该单词出现在句子中,则该条目的分数将低于
我正在尝试在我的应用程序委托(delegate)方法中实现一些逻辑。了解当前正在运行哪种场景将非常有帮助。 [[CCDirector sharedDirector] runningScene] 返回当
好的,这是一个有趣的。我有 2 个表:tbl_notes、tbl_notes_categories 简单地说,tbl_notes 有一个 categoryid,我将 2 个表与该 ID 相关联。所以,
我有一个使用并行运行的 Specflow、selenium、NUnit 的测试解决方案在 AssemblyInfo 中添加了这个:[程序集:Parallelizable(ParallelScope.F
我正在尝试弄清楚如何在 SpriteKit 中添加更多场景。如果我在 GameViewController 中使用 SpriteKit 生成的行 if let scene = GameScene.un
目录 1、业务背景 2、场景分析 3、流程设计 1、业务流程 2、导入流程
我是 Unity 的新手,所以修复起来可能非常简单。我使用了一个 3D Google SketchUp 模型,我想让玩家环顾模型。 super 简单。 我添加了 3D 平面,添加了相机并更新了设置以支
我需要标记要跳过的某些测试。但是,有些测试是参数化的,我只需要能够跳过某些场景。 我使用 py.test -m "hermes_only" 调用测试或 py.test -m "not hermes_o
我已经开始使用 SpecFlow 并想知道是否可以在规范之间重用场景 基本上我的想法是这样的(我可能从根本上是错误的:)) 我编写了一项功能来验证导航。 功能:导航 I should be able
在编写验证输入表单上的信息的 BDD 场景时,您将如何列出规则。 选项是: 1) 每个规则一个场景 2)场景大纲,每个领域和规则的例子 我们如何说某些不在特定字符集中的无效内容,例如: 鉴于我输入了一
我们如何使用 StoryQ 来测试预期出现异常的场景? 最佳答案 就实际代码而言,在测试代码的 .Then 部分,您需要创建一个 Action 或 Func 来确定正在测试的内容,然后在代码的 .Th
完成快速初学者努力通过点击按钮向场景添加节点。 我知道我可以使用点击手势来获取点击坐标并执行点击测试,然后在点击的 3D 空间中放置一个对象。但是,我想在设备屏幕的中央显示一个球体或十字准线,当点击屏
如何在表格中传递空格? Background: Given the following books |Author |(here several spaces)
我正在尝试从 Eric Haines' Standard Procedural Database (SPD) 渲染“mount”场景,但折射部分就是不想配合。我已经尝试了所有我能想到的方法来修复它。
我是一名优秀的程序员,十分优秀!