OSG在事件处理中由于模态对话框导致后续事件出错的问题

osgcamera例子 这个例子是一个多相机、多视口的例子,我们有机会研究一下OSG中的视口相机。 首先,程序最外面run了两次,通过EnableVBOVisitor的方式使用了定点缓冲对象,EnableVBOVisitor继 承自NodeVisitor,在accept的时候执行一次,执行NodeVisitor中的apply方法。 enum TraversalMode         { 阅读详情

问题描述:

在OSG的事件处理GUIEventHandler中,当我们需要操作打开一个模态对话框(非模态的对话框并没有问题)的时候,在关闭模态对话框之后导致后续的事件处理异常。


本文以osgQt为例,描述这一问题的出现以及解决方式。程序很简单,在窗口中点击右键弹出对话框,加载选择的模型。代码如下:

class ViewerWidget : public QWidget, public osgViewer::Viewer
{
	Q_OBJECT
public:
	ViewerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0): QWidget(parent, f)
	{
		setThreadingModel(ViewerBase::SingleThreaded);
		QWidget* renderWidget = createViewWidget(createGraphicsWindow(0, 0, 100, 100), nullptr);

		QGridLayout* grid = new QGridLayout;
		grid->addWidget(renderWidget, 0, 0);
		grid->setMargin(1);
		setLayout(grid);

		_testHandler = new TestHandler();
		this->addEventHandler(_testHandler);


		connect(_testHandler, SIGNAL(rightButtonClickedSignal()), this, SLOT(rightButtonClickedSlot()));
		connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
		_timer.start(10);
	}

	QWidget* createViewWidget(osgQt::GraphicsWindowQt* gw, osg::Node* scene)
	{
		osg::Camera* camera = this->getCamera();
		camera->setGraphicsContext(gw);

		const osg::GraphicsContext::Traits* traits = gw->getTraits();

		camera->setClearColor(osg::Vec4(0.2, 0.2, 0.4, 1.0));
		camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
		camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width) / static_cast<double>(traits->height), 1.0f, 10000.0f);

		this->setSceneData(scene);
		this->setCameraManipulator(new osgGA::TrackballManipulator());

		return gw->getGLWidget();
	}

	osgQt::GraphicsWindowQt* createGraphicsWindow(int x, int y, int w, int h, const std::string& name = "", bool windowDecoration = false)
	{
		osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
		osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
		traits->windowName = name;
		traits->windowDecoration = windowDecoration;
		traits->x = x;
		traits->y = y;
		traits->width = w;
		traits->height = h;
		traits->doubleBuffer = true;
		traits->alpha = ds->getMinimumNumAlphaBits();
		traits->stencil = ds->getMinimumNumStencilBits();
		traits->sampleBuffers = ds->getMultiSamples();
		traits->samples = ds->getNumMultiSamples();

		return new osgQt::GraphicsWindowQt(traits.get());
	}

	virtual void paintEvent(QPaintEvent* event)
	{
		frame();
	}

public slots:
	bool rightButtonClickedSlot();

protected:

	QTimer _timer;
	TestHandler* _testHandler;
};

该类中添加的TestHandler的代码如下:

	bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
	{
		switch (ea.getEventType())
		{
		case osgGA::GUIEventAdapter::PUSH:
		{
			if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
			{
				 QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"),
					"/home",
					tr("Models (*.osg *.osgb *.osgt)"));

				 if (!fileName.isEmpty())
				 {
					 QByteArray fileByteArray = fileName.toLocal8Bit();
					 std::string fileNameStdString = fileByteArray.constData();

					 osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
					 if (viewer)
					 {
						 viewer->setSceneData(osgDB::readNodeFile(fileNameStdString));
					 }
				 }

			}

			return false;
		}
		break;


		case osgGA::GUIEventAdapter::DRAG:
		{
			if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
			{
				return false;
			}
			else if (ea.getButtonMask() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
			{
				return false;
			}

			return false;
		}

		case osgGA::GUIEventAdapter::MOVE:
		{
			return false;
		}

		default:
			break;
		}
		return false;
	}

运行程序,在点击右键之后弹出打开文件的对话框,选择osg的文件之后,发现场景加载进来之后鼠标在移动的时候触发了右键的Drag事件,导致模型一直在缩放中。


鼠标的Move事件被解析为了右键的Drag事件(感觉上是右键一直在被按下的效果)。

解决方式:

出现的原因暂时未知,但是感觉上是OSG的事件封装和Qt的事件出现了冲突,于是将弹窗放到Qt的事件中处理:

让TestEventHandler继承自QObject,并将窗体的事件处理器安装在EventTest上,在事件处理器中处理右键点击打开文件:

class TestHandler : public QObject, public osgGA::GUIEventHandler
{
	Q_OBJECT

public:
	TestHandler(QWidget *w)
	{ 
		_widget = w;
	}

	~TestHandler(){ }


	bool eventFilter(QObject *obj, QEvent *event)
	{
		if (event->type() == QEvent::MouseButtonPress)
		{
			QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
			if (mouseEvent->button() == Qt::RightButton)
			{
				QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"),
					"/home",
					tr("Models (*.osg *.osgb *.osgt)"));

				if (!fileName.isEmpty())
				{
					QByteArray fileByteArray = fileName.toLocal8Bit();
					std::string fileNameStdString = fileByteArray.constData();

					osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(_widget);
					if (viewer)
					{
						viewer->setSceneData(osgDB::readNodeFile(fileNameStdString));
					}
				}

				return true;
			}
			else
			{
				return QObject::eventFilter(obj, event);
			}
			
		}
		else {
			return QObject::eventFilter(obj, event);
		}
	}



	bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
	{
		switch (ea.getEventType())
		{
		case osgGA::GUIEventAdapter::PUSH:
		{
			//if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
			//{

			//}

			return false;
		}
		break;


		case osgGA::GUIEventAdapter::DRAG:
		{
			if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
			{
				return false;
			}
			else if (ea.getButtonMask() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
			{
				return false;
			}

			return false;
		}

		case osgGA::GUIEventAdapter::MOVE:
		{
			return false;
		}

		default:
			break;
		}
		return false;
	}


signals:
	bool rightButtonClickedSignal();


protected:
	QWidget* _widget;
};

同时在主窗口的构造函数中安装这个事件处理器

		_testHandler = new TestHandler(this);
		this->addEventHandler(_testHandler);
		renderWidget->installEventFilter(_testHandler);

修改代码之后再次运行程序,右键调出对话框选择文件加载之后,一切正常了。


本文提供了一种处理的思路,其实也可以不用事件过滤这种方式来做,直接在主窗体的事件中处理即可。只是想说明这个问题的处理方式是让弹窗的处理在Qt中进行。这可能是OSG的一个事件封装的Bug。





新大陆虚拟仿真软件:从物理引擎到工业应用的技术架构与实践 虚拟仿真技术通过计算机模拟真实世界的物理过程与系统行为,其核心原理在于集成物理引擎、数学模型与实时渲染,构建高保真的数字孪生环境。这项技术的价值在于能以低成本、零风险的方式,在数字空间中预测、分析和优化复杂系统,从而驱动产品创新与效率提升。其应用场景广泛,尤其在工业制造领域,如复杂装备的操作培训、产品装配工艺验证以及多学科协同研发中发挥着关键作用。本文以“新大陆”项目为例,深入探讨了如何通过分层解耦的架构设计,融合NVIDIA PhysX等物理引擎与OpenSceneGraph渲染技术,并集成力反馈设备与V 阅读详情

相关推荐

3dsMax2020必备插件:一键解决材质混乱问题(附安装避坑指南)

本文深入解析了3dsMax2020中材质混乱的根源,并推荐了一款必备的专业插件。该插件通过智能实例化功能,自动合并重复材质与贴图,有效释放内存、提升渲染性能。同时提供高级重命名、贴图路径批量修复等工具,系统化解决材质管理难题,重塑高效、稳定的3D工作流。

l6m7n8的博客 232

osg--提高效率

多线程 OpenThreads::Thread 虚函数 cancel() run() OpenThreads::Mutex OpenThreads::Barrier OpenThreads::Condition 线程管理 GetNumberOfProcessors() 处理器数目获取 SetProcessorAffinityOfCurrentThread() 当前线程使用处理器设...

蓝蓝的天 1283

电表协议避坑指南:DLT645-2007与Modbus RTU的5大核心差异对比

本文深入对比了DLT645-2007与Modbus RTU两大电表通讯协议的核心差异,涵盖协议定位、数据地址、报文结构及实测性能。DLT645-2007作为电力行业标准,数据定义统一但效率受限;Modbus RTU作为通用协议,灵活高效但需依赖厂家点表。文章结合实测数据与开发经验,为不同场景下的协议选型与编程实践提供了清晰的避坑指南。

weixin_29166013的博客 108

osgViewer::ViewerBase 线程模型(_threadingModel )

函数: 1.setThreadingModel(ThreadingModel threadingModel) 设置线程模型 enum ThreadingModel { SingleThreaded, CullDrawThreadPerContext, ThreadPerContext = CullDrawThreadPerContext, DrawThreadPerContext,...

YU_19840311的专栏 1411

HPC软件使用之ANSYS Fluent

本文介绍了如何在超级计算机上使用ANSYS Fluent进行科学计算和工程仿真。文章首先对Fluent软件进行了简要介绍,强调了其在计算流体力学领域的广泛应用和强大功能。接着,详细说明了如何编写jou脚本文件和slurm脚本文件,以控制Fluent的计算流程和作业提交。文章还提供了作业提交和查看的具体命令,并通过一个鼓风机仿真的案例演示了从网格模型准备、脚本编写、作业提交到结果查看的完整流程。最后,展示了使用Fluent进行结果可视化的方法。

欢迎各位大佬光临“寒舍”!请多多指点,共同进步! 2212

基于浏览器插件的拼多多买家订单导出方法

基于浏览器插件的拼多多买家订单导出方法

2501_93542170的博客 1723

C++学习(三二一)GUIEventAdapter::MOVE与GUIEventAdapter::DRAG区别

MOVE没有鼠标左键按下移动,DRAG鼠标左键按下移动 osgGA/GUIEventAdapter class OSGGA_EXPORT GUIEventAdapter : public Event { enum EventType { NONE = 0, PUSH = 1<<0, RELEASE = 1<<1

hankern的专栏 743

给麒麟KylinOS服务器加把锁:手把手配置符合等保要求的密码强度策略

本文详细介绍了如何在麒麟KylinOS服务器上配置符合等保要求的密码强度策略,包括pwquality.conf和login.defs的核心参数设置、等保合规的进阶配置技巧以及企业环境中的平衡艺术。通过实战案例和测试方法,帮助管理员构建坚固的密码防线,确保系统安全。

weixin_33749242的博客 419

osgViewer::Viewer详解

osgViewer::Viewer详解 l         构造函数Viewer::Viewer(osg::ArgumentParser& arguments)可以做一些初始化工作,比如当读取参数--clear-color时,可以设置背景颜色。详细请参考源码。建议不使用。l         函数setThreadingModel设置线程模型SingleThreaded - 单CPU

boqing的专栏 1万+

Python控制TEMI1000/TEMI1500测试温箱

该温箱是我司从昆山振弘检测设备有限公司采购的TEMI 1000,但是控制器用的是韩国的,关于控温箱这个项目,可参考的资料仅有一份官方的manual,里面包含一些命令格式。只要你有温箱,就应该可以向厂家索取该文档。该温箱的通讯接口只有一个RS232接口,要想实现远程控制,需要有串口转USB的线;类似于下图所以,想依靠python来与之进行通信,还是要通过python 的pyserial库,关于怎么安装pyserial,过于简单,这里不做赘述,可自行百度。

xgh1951的博客 1万+

如何使用DPABI 进行核磁共振数据结果统计分析?

下面总结使用DPABI 的统计模块对MRI 图像进行统计分析的基本方法,并与SPM 的统计结果进行简单的对比。DPABI 的统计模块包含了常用的统计模型和多重比较校正方法、在控制协变量上也非常方便。 DPABI 进行结果统计分析一、下载和安装 DPABI二、下载样例数据三、统计模型和多重比较校正四、DPABI 的统计主界面五、DPABI 的可视化主界面六、查看统计结果 一、下载和安装 DPABI 下载 DPABI 包,解压后将文件夹和子文件夹加入MATLAB 的搜索路径即可。 具体安装方法详见 dpabi

从事脑科学核磁共振方法学研究,在Nature communications等权威期刊发表研究论文,熟练掌握磁共振处理方法和统计学方法,欢迎大家和我交流。 1万+

osg解析系列-需要将osg嵌入其他平台窗口时(MFC/QT/X),请使用osgViewer::GraphicsWindowEmbedded

SceneView已弃用,还保留它仅为了向后兼容。需要嵌入式渲染支持时,建议使用 osgViewer::Viewer 和 osgViewer::GraphicsWindowEmbedded组合使用,osgViewer::GraphicsWindowEmbedded提供了更大范围的功能和一致性的API。

qq_42531872的博客 857

基于STM32L4XX、HAL库的MP2672GD-0000-Z充电芯片驱动程序设计

CHG_STAT_GPIO_Port, CHG_STAT_Pin, // 这些宏应由 CubeMX 生成在 main.h。

zhusl6688的博客 497

OSG视景器四种线程模型(摘自Array《最长的一帧》)

OSG 的视景器包括四种线程模型,可以使用setThreadingModel 进行设置,不同的线程 模型在仿真循环运行时将表现出不同的渲染效率和线程控制特性。通常而言,这四种线程的 特性如下: SingleThreaded:单线程模型。OSG 不会创建任何新线程来完成场景的筛选和渲染,因 而也不会对渲染效率的提高有任何助益。它适合任何配置下使用。 CullDrawThreadPerCon

ZhangXL的专栏 4148

代谢组数据分析(十五):基于python语言构建PLS-DA分类预测模型

本教程阐述典型代谢组学数据分析工作流程,用于二元分类结果的研究。流程主要步骤如下:首先从 Excel 表格导入代谢物与实验数据,接着基于汇总 QC 进行数据清洗。随后借助主成分分析可视化检查数据质量,再开展两类单变量统计。之后运用偏最小二乘判别分析(PLS - DA)实施多变量分析,此过程涵盖模型优化(对比 R2 与 Q2)、置换测试及明确模型预测指标、确定特征重要性、对模型预测数据进行可视化。最终将统计表格导出至 Excel 表格,完整呈现从数据导入到分析结果输出的全过程。

专注生信领域 2876

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

osgDB::readNodeFile 失败

之前的倾斜摄影,tif等数据文件都没有问题。 突然发现,.osg文件无法加载。 osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg"); 错误: SGReaderWriter wrappers failed to load Error reading file d:\img\cow.osg: read error (No data loaded) 网上查询了一溜八开,试了半天也没有找到原因。 最后偶尔切换到Release版

alibaba00的博客 2740

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

OSG人机交互

OSG人机交互

小猿一枚的专栏 2362

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

7、osg中响应键盘鼠标事件以及鼠标和键盘编码表

1、首先定义一个类,该类继承与osgGA::GUIEventHandler,在此类中存在一个handle函数,所有的事件都在此函数中进行处理,如下类的代码: //声明类UseEventHandler,由于它是从osgGA::GUIEventHandler派生而来,所以它拥有处理事件的能力,其中这种能力体现在一个虚函数handle上。 //一切的处理都在handle当中。 class UseEve

sxj的专栏 9753

osg程序中osgDB::writeNodeFile和osgDB::readNodeFile总是失败

前言 osg程序中osgDB::writeNodeFile和osgDB::readNodeFile总是失败,比如下面的代码: int main(int argc, char** argv) { osg::ref_ptr<osg::Node> root = createSceneGraph(); if (!root.valid()) { osg::notify(osg::FATAL) << "Faile to createSceneGraph()

aoxuestudy的专栏 4164

场景交互与场景漫游-osgGA库(5)

osg 场景交互与场景漫游-osgGA库

liangfei868的博客 1176

osg中添加到球面上的模型实现沿地形拖拽功能

最近做了一个鼠标点击在球面点击位置添加模型的功能,现在要求实现拖拽功能。Pick到球面上的模型的时候模型高亮显示,然后可沿地表拖拽,释放的时候高亮消失,模型拖拽结束,步骤如下: 1、新建一个继承自osgGA::GUIEventHandler的类DragHandle,重载函数handle(),和增加成员函数Pick(); 2、在函数handle()中将会判断3个事件,PUSH、DRAG、和REL

u012463389的博客 2910

osg鼠标点选类

  添加了注释便于理解 class mousehandle:public osgGA::GUIEventHandler { public: mousehandle(){} ~mousehandle(){} void pick(osgViewer::View* view,float x,float y); bool handle(const osgGA::GUIEventAdapter...

l_null的博客 1214

osgearth仿真平台之测量工具(2)

osgearth距离和面积测量方法

weixin_41157291的博客 2003

OSG osgDB::readNodeFile 读取ply文件

osgDB::readNodeFile 函数通常读取 osg、ive格式文件, 后来发现也可以直接读取点云 ply文件 但是发生报错:

qing101hua的专栏 6606

osg控制节点的显示与否

使物体或者说Node隐藏方式有两种,一种是设置NodeMask,另外一种是使用osg的switch类来控制。 两者的区别是 前者只是看不到,数据还在场景中,隐藏了并不能影响渲染性能,不影响内存中的数据; 后者是从内存中暂时移除,会对性能有所影响,需要显示时再加载进场景。 回调的速度好像是每帧调用一次,这样程序运行起来,会看到球以很快的速度在闪。为了更方便的观察,我在回调中做了限

GreenArrowMan-优快云博客 2264
上一篇: Skyline Globe中3dml图层的遍历
下一篇: C++中typedef和类型别名
csxiaoshui
博客等级 码龄16年 873粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值