qt graphicsview中,js wheeleventt函数重写,如何过滤掉滚动条对函数的影响?

一、Qt中事件处理的方式
1、事件处理模式一
& & & & 首先是事件源产生事件,最后是事件处理器对这些事件进行处理。然而也许大家会问,
Qt中有这么多类的事件,我们怎么样比较简便的处理每个事件呢?设想,如果是每个事件都对应同一个事件处理器,在该事件处理器中对不同的事件进行分类处理,这样的弊端有两点:第一,导致该事件处理器过于臃肿复杂;第二,这样不便于扩展,当系统新增加事件类型或者是我们需要使用到自定义事件时,就不得不修改Qt的源码来达到目的。所以Qt设计者的做法是针对不同类型的事件提供不同的事件处理器与之对应。这里又有一个问题了,Qt中是怎么让不同类型事件与之对应的事件处理器相关联的呢?我们不难猜想在事件和事件处理器中间必定有一个桥梁。这个桥梁就是QObject::event()函数,该函数是虚函数,QObject的子类例如QWidget都实现了该函数。该函数的主要功能是进行事件的分发,也就是将不同类型的事件与之相对应的事件处理器相关联,该函数并不对事件进行处理,真正的事件处理是在事件处理器中进行的。
& & & & 例如:当QWidget产生QPaintEvent事件后,QWidget的event函数会将该事件分发给QWidget::paintEvent()事件处理器,这样该事件就得到处理了。
以上内容用一个图形表示就是:
2、事件处理模式二
& & & & 很多时候,我们只对某些特定的事件比较关心,例如:鼠标单击或者键盘按下等事件。其它的事件我们并不关心它是否发生,也无需对它们进行处理,这个时候最直接的想法就是将这些事件过滤掉,这样做既可以免去对它们进行处理,也可以避免它们对程序其它部分产生影响。因此,处理模式二中我们引入了事件过滤器这个概念。
& & & & 如果对象安装了事件过滤器,则事件在到达目标对象之前先被事件过滤器截获,进行一些处理之后再交给目标对象,该模式总结为一个图如下:
注意:这里需要区别对待,如果你是使用installEventFilter()函数给目标对象注册事件过滤器,那么该事件过滤器只对该目标对象有效,只有该对象的事件需要先传递给eventFilter()函数进行过滤,然后调用相应的事件处理器进行处理,非目标对象则不受影响。如果你是给程序中唯一的QApplication对象注册事件过滤器,那么该过滤器对程序中的每一个对象都有效,任何对象的事件都是先传给eventFilter()函数,然后再使用事件处理器进行处理。
3、事件处理模式三
& & & & Qt调用QApplicaton来发送一个事件。所以我们可以重新实现QApplication中的notify()函数来获取事件并进行处理,而且使用该函数获取事件的时间要早于事件过滤器获取事件的时间。但是使用事件过滤器较为简便,因为我们可以有多个事件过滤器,但是只能有一个notify()函数。用一个图来总结该模式就是:
二、Qt中事件处理的方法
& & & & 从以上三个处理模式我们可以看出,这是一个不断完善的过程,从3个模式的讨论中我们不难找到可以进行事件处理的地方,而这几个地方就是我们在编写程序的时候可以控制事件处理的地方。1、event()函数首先是控制事件分发的event()函数,我们可以改写该函数,改变事件的分发方式,这样就可以改变事件处理的结果。2、notify()函数实现该函数可以截获事件,并对事件加以处理,但是该方法很少用,这里不做介绍。3、事件过滤器实现自己的事件过滤器就可以改变事件处理的方法和结果,这个方法比较常用。4、事件处理器事件处理的最后一步,也是最重要的一步就是事件处理器,因为它才是真正进行事件处理的地方,我们可以改写以有的事件处理器,以此改变已有事件的处理方法和处理结果,我们也可以定义自己的事件类型和相应的事件处理器。
注意:以上四种方法中最常用的是后两者:事件过滤器和事件处理器。
补充内容:
1、事件的传递
& & & & 包括鼠标和键盘事件在内的很多事件都可以被传递。如果事件在到达目标对象之前没有被截获处理,或者已经传递给了它的目标对象但目标对象并没有进行处理,那么此时,目标对象的父对象将变成新的目标对象,整个事件处理的过程将重复进行,直到该事件被处理或者到达最顶层对象为止。
2、event实例解析
& & & &下面的代码是QWidget::event()函数的代码,从代码中可以看出event()函数确实只进行事件的分发而不负责事件的处理。由于函数代码过多,且都是一类型的用switch语句进行处理的,这里只贴出一部分代码:
bool&QWidget::event(QEvent&*event)&&
&&&&Q_D(QWidget);&&
&&&&if&(!isEnabled())&{&&
&&&&&&&&switch(event-&type())&{&&
&&&&&&&&case&QEvent::TabletPress:&&
&&&&&&&&case&QEvent::TabletRelease:&&
&&&&&&&&case&QEvent::TabletMove:&&
&&&&&&&&case&QEvent::MouseButtonPress:&&
&&&&&&&&case&QEvent::MouseButtonRelease:&&
&&&&&&&&case&QEvent::MouseButtonDblClick:&&
&&&&&&&&case&QEvent::MouseMove:&&
&&&&&&&&case&QEvent::TouchBegin:&&
&&&&&&&&case&QEvent::TouchUpdate:&&
&&&&&&&&case&QEvent::TouchEnd:&&
&&&&&&&&case&QEvent::ContextMenu:&&
#ifndef&QT_NO_WHEELEVENT&&
&&&&&&&&case&QEvent::Wheel:&&
&&&&&&&&&&&&return&&&
&&&&&&&&default:&&
&&&&&&&&&&&&&&
&&&&&&&&}&&
&&&&switch&(event-&type())&{&&
&&&&case&QEvent::MouseMove:&&
&&&&&&&&mouseMoveEvent((QMouseEvent*)event);&&
&&&&&&&&&&
&&&&case&QEvent::MouseButtonPress:&&
&&&&&&&&resetInputContext();&&
&&&&&&&&mousePressEvent((QMouseEvent*)event);&&
&&&&&&&&&&
&&&&case&QEvent::MouseButtonRelease:&&
&&&&&&&&mouseReleaseEvent((QMouseEvent*)event);&&
&&&&&&&&&&
&&&&case&QEvent::MouseButtonDblClick:&&
&&&&&&&&mouseDoubleClickEvent((QMouseEvent*)event);&&
&&&&&&&&&&
#ifndef&QT_NO_WHEELEVENT&&
&&&&case&QEvent::Wheel:&&
&&&&&&&&wheelEvent((QWheelEvent*)event);&&
&&&&&&&&&&
#ifndef&QT_NO_TABLETEVENT&&
&&&&case&QEvent::TabletMove:&&
&&&&case&QEvent::TabletPress:&&
&&&&case&QEvent::TabletRelease:&&
&&&&&&&&tabletEvent((QTabletEvent*)event);&&
&&&&&&&&&&
http://blog.csdn.net/chenlong12580/article/details/7720365
Views(...) Comments()QT 重写QGraphview的paintEvent函数,函数中drawRect没效果,且函数无限循环_VC DataGrid控件使用有关问题_刚开始学,有个有关问题一直搞不懂,请各位大神帮帮忙__脚本百事通
稍等,加载中……
^_^请注意,有可能下面的2篇文章才是您想要的内容:
QT 重写QGraphview的paintEvent函数,函数中drawRect没效果,且函数无限循环
VC DataGrid控件使用有关问题
刚开始学,有个有关问题一直搞不懂,请各位大神帮帮忙
QT 重写QGraphview的paintEvent函数,函数中drawRect没效果,且函数无限循环
QT 重写QGraphview的paintEvent函数,函数中drawRect没有效果,且函数无限循环
这是全部代码,程序一直在paintEvent中死循环,而且画不出矩形,求解
------解决方案--------------------别使用它的paintEvent(),要绘制图形需要重写GGraphicsItem中的paint()纯虚函数。或者你也可以覆盖写QGraphicsView的drawBackground()或drawForeground()函数。------解决方案--------------------为何要弹一个messagebox。。肯定死循环啊。。
你刚点了ok。。没有显示的那部分又要绘制,会触发panitEvent。------解决方案--------------------为什么要在view中重写paintEvent..一般是在scene上加item,然后重写item的paint
VC DataGrid控件使用有关问题
VC DataGrid控件使用问题在一个工程中使用了控件DataGrid,发现客户机上使用时控件没有显示,是不是因为客户机没有安装该控件?如果客户机要装DataGrid控件,这个控件在VC安装目录下有吗?可以考出来装到客户机上去吗?
------解决方案--------------------一个工程中使用了控件DataGrid,安装就应该带这个, 即使 客户端 有 也有 版本 问题。------解决方案--------------------c:\windows\system32\msdatgrd.ocx
该文件需要注册------解决方案--------------------msadodc.ocx
刚开始学,有个有关问题一直搞不懂,请各位大神帮帮忙
刚开始学,有个问题一直搞不懂,请各位大神帮帮忙关于“float”和“double”的选取问题.什么时候选择"float"什么时候用“double”,请各位帮帮忙,劳烦详细一点。谢谢
------解决方案--------------------主要看取值范围,他们的取值范围不同------解决方案--------------------http://blog.csdn.net/ccy3253/article/details/2070616------解决方案--------------------float是单精度浮点,每个数用4个字节,而double是双精度浮点,每个数用8个字节。
如果是科学计算等要求精度较高的地方,用double。
如果精度要求不高,可以用float。
如果是金额计算,最好用decimal。
如果您想提高自己的技术水平,欢迎加入本站官方1号QQ群:&&,&&2号QQ群:,在群里结识技术精英和交流技术^_^
本站联系邮箱:QT 的 Graphics View 系统 - JefferyZhou - 博客园
这个框架是一个相对成熟的渲染引擎的上层框架,通常也可以会叫做 Scene - View。 在QT中,GraphicsView是一个与QWdiget系列一点点不一样的系统。这个系统主要由下面几个框架类构成:QGraphicsView,& QGraphicsScene, QGraphicsItem
QGrahpicsView是从原生的QWidget继承过来,QGraphics-View系统中,他承担的也是视口的指责,Viewport,Viewport相当于显示设备的一个矩形区域。 QGraphicsScene 是一个管理器,用来管理所有的QGraphicsItem,包括根据坐标查询Item,排序Item,绘制Item等。 QGraphicsItem 是所有可见的元件。一个完整的UI界面,由各种QGraphicsItem组合起来。这些QGraphicsItem之间由一棵多叉树组织。 要架构一个基于GraphicsView的UI库,需要做如下的三件事情:
我们需要先由一个 QGraphicsView, 这个是UI显示的地方,也就是装满可见原色的Scene,
然后需要一个QGraphicsScene 用来管理所有可见的界面元素,
要实现UI功能,我们需要用各种从QGraphicsItem拼装成UI控件,并赋予他控件的逻辑。 对应到Duifw,我们的DuiFrameWindow 就是从 QGraphicsView 继承过来的,也就是说它是一个独立的视口,相当于操作系统的一个窗口. 在DuiFrameWindow 中 void DuiFrameWindow::_initScene(), 函数中,我们为每一个 DuiFrameWindow 创建了一个标准的 QGraphicsScene,& 并且在 scene 上我们 add 了一个 DuiRootItem,然后我们就在 rootitem上构建我们的所有UI控件,& 从& DuiRootItem: m_rootItem 上 我们add 三个子Item ,分别是 DuiBackgroundItem:m_backgroundItem, DuiTitlebar:m_titlebar, DuiSpacerItem:m_contentItem, 然后我们定义了一个rootWidget() 函数 用来返回& DuiSpacerItem:m_contentItem, 后面通过xml文件配置的一个窗口,就通过访问rootWidget(), 把所有DuiFrameWindow的孩子节点都以 这个rootWidget为 父节点,如下代码: createChild(child-&child(index), frame-&rootWidget()); 这样就构建了一个QGraphicsItem的多叉树。前面有一个细节,没有列出,就是我们的DuiWidget, 是一个什么, 我们的DuiWidget是从QGraphicsWidget,继承而来的,也就是说它本身是一个符合 QGraphicsScene - QGraphicsItem体系的可视元件。 了解了的GraphicsView的构成框架后,对于QGraphicsItem的消息来源,以及这个框架中的消息走向能够大概有了猜测了。 QGraphicsView 会把& 原来的QWidget中的各种QHoverEvent, QInputEvent,......等等一些列命令,转换成各种 QGraphicsSceneEvent ,QGraphicsSceneMouseEvent,QGraphicsSceneWheelEvent......,,,然后传递给当前View绑定的QGraphicsScene。然后通过Scene传递给 QGraphicsitem,QGraphicsScene 有如下的一堆消息处理接口:
通过上述的分发,最后消息会通过下面的接口传递到具体的item,所有的scene消息都是走接口:
这样就完成了从windows消息到 QGraphicsItem 的消息处理的流程。 到此。QGraphics - View 框架就简述完成了。Qt的GraphicsView框架和OpenGL结合详解
Qt的Graphics-View框架和OpenGL结合详解
演示程序下载地址:这里
程序源代码下载地址:这里
这是一篇纯技术文,介绍了这一个月来我抽时间研究的成果。
Qt中有一个非常炫的例子:Boxes,它展示了Qt能够让其Graphics–View框架和Qt的OpenGL模块结合起来,渲染出非常出色的效果。其实我私自认为凭这个程序,已经有很多游戏开发者关注Qt了,因为游戏开发一个非常常见的模块就是UI,一般情况下游戏引擎提供的UI模块比较弱,基本上都是游戏引擎+第三方GUI库进行结合的。但是Qt以其Graphics–View框架能够非常轻松地将UI控件嵌入场景中,而且能够和OpenGL底层共存,更重要的是,凭借着Qt的qss,Qt可以定制许多GUI元素,这是非常具有吸引力的。所以说,如果大家对游戏开发感兴趣,那么不妨看一下Qt。
好了,下面介绍一下前几天我制作并发布的一个demo。这个demo是对Boxes这个例子进行模仿,结合学习《OpenGL超级宝典》,制作而成的,由于最近比较忙,所以总共花了将近一个月才完成,不得不说效率有点儿低。
首先从MainWindow.cpp这个文件说起吧,一开始是要初始化MainWindow类的,这个类是继承QMainWindow的,这里重点说说它的构造函数:
MainWindow::MainWindow( QWidget* pParent ):
QMainWindow( pParent )
QGLWidget* pWidget = new QGLWidget( QGLFormat( QGL::SampleBuffers ), this );
pWidget-&makeCurrent( );
// scene的内容
GraphicsScene* pScene = new GraphicsScene( this );
OpenGLView* pView = new OpenGLView( this );
pView-&setViewport( pWidget );
pView-&setViewportUpdateMode( QGraphicsView::FullViewportUpdate );
pView-&setScene( pScene );
// 选择不同的着色器的时候进行着色器连接
connect( pScene, SIGNAL( SwitchShader( const QString& ) ),
pView, SLOT( SwitchShader( const QString& ) ) );
connect( pScene, SIGNAL( SetLightPos( const QVector3D& ) ),
pView, SLOT( SetLightPos( const QVector3D& ) ) );
setCentralWidget( pView );
setWindowTitle( tr( &Light for shader& ) );
resize( 640, 360 );
首先在我们创建了一个QWidget,然后调用makeCurrent()成员函数,其实意思是让它的rendercontext设为当前的rendercontext。随后建立的是OpenGLView,这个OpenGLView是来自于QGraphicsView的,它的初始化和其祖先的并无二致,随后一句非常重要:setViewport(),它的作用是将QGLWidget设置为OpenGLView的viewport,这样的话背景的rendercontext不再是rastercontext而是OpenGLcontext了,否则场景的背景还是需要用CPU渲染的,效率低下。接着是两段建立连接的代码。最后设置的是窗口大小和标题什么的,一开始还是非常简单的。
接下来我们看看OpenGLView是怎么定义的:
class OpenGLView: public QGraphicsView,
protected QOpenGLFunctions
OpenGLView( QWidget* pParent = 0 );
virtual ~OpenGLView( void );
void setScene( GraphicsScene* pScene );
public slots:
bool SwitchShader( const QString& shaderFileName );
void SetLightPos( const QVector3D& lightPos = QVector3D( ) );
protected:
void resizeEvent( QResizeEvent* pEvent );
void mousePressEvent( QMouseEvent* pEvent );
void mouseReleaseEvent( QMouseEvent* pEvent );
void mouseMoveEvent( QMouseEvent* pEvent );
void wheelEvent( QWheelEvent* pEvent );
void drawBackground( QPainter* pPainter, const QRectF& rect );
void InitGL( void );
void ResizeGL( int width, int height );
void PaintGL( void );
void DrawAxis( void );
bool SetupShaders( void );
QOpenGLShader*
m_pVertexShader;
QOpenGLShaderProgram* m_pShaderProgram;
这里我们在它的成员中添加了一个摄像机,一个3ds模型实例,还有一个顶点着色器和着色器程序类。在上次的博客中讲到了在这种情况最好使用类指针而不是类成员作为数据成员,这里我索性把着色器程序类也做成了指针成员了。
由于OpenGLView类实现比较长,这里我着重说一下其中的几个函数。下面是drawBackground()函数的实现:
void OpenGLView::drawBackground( QPainter* pPainter,
const QRectF& )
pPainter-&beginNativePainting( );
glPushAttrib( GL_ALL_ATTRIB_BITS );
InitGL( );
ResizeGL( pPainter-&device( )-&width( ),
pPainter-&device( )-&height( ) );
PaintGL( );
glPopAttrib( );
pPainter-&endNativePainting( );
为什么选择drawBackground()?因为我们想要得到一种效果,OpenGL在底层绘制,上面绘制控件,其实自从QPainter有了beginNativePainting()和endNativePainting()这两个函数,我们就可以进行纯OpenGL的绘制了。这里还要注意的是,因为绘制控件也是使用OpenGL的context,这样简单调用会让OpenGL的状态混乱,所以需要将各种状态通过glPushAttrib(GL_ALL_ATTRIB_BITS);保存起来,然后初始化我们的OpenGL状态,以及绘图,最后记得glPopAttrib();还原所有状态供2D绘制。这里就不像以往的GLWidget套路了,因为GLWidget里面的initializeGL()函数只调用一次,paintGL()函数调用多次,但是在这里,只要有刷新的消息(通过update()或repaint()触发),就必须调用InitGL()函数来进行OpenGL状态的设置,否则先前设置的所有状态都消失了。
接下来看看ResizeEvent()函数:
void OpenGLView::resizeEvent( QResizeEvent* pEvent )
scene( )-&setSceneRect( 0.0,
pEvent-&size( ).width( ),
pEvent-&size( ).height( ) );
pEvent-&accept( );
这里由于我们已经设置了scene为GraphicsScene类的实例指针,因此scene()是非空的,我们将场景限制为view的大小,这样可以避免一些刷新的问题。
而paintGL()函数也是相当的简单。
void OpenGLView::PaintGL( void )
glClear( GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT );
glPushMatrix( );
m_Camera.Apply( );
m_3DS.RenderGL( );
if ( g_ShowAxis ) DrawAxis( );
glPopMatrix( );
接着我向大家介绍一下GraphicsScene类:
class GraphicsScene: public QGraphicsScene
GraphicsScene( QObject* pParent = 0 );
void SetCamera( Camera* pCamera );
void SwitchShader( const QString& shaderFileName );
void SetLightPos( const QVector3D& pos );
protected:
void mousePressEvent( QGraphicsSceneMouseEvent* pEvent );
void mouseMoveEvent( QGraphicsSceneMouseEvent* pEvent );
void mouseReleaseEvent( QGraphicsSceneMouseEvent* pEvent );
void wheelEvent( QGraphicsSceneWheelEvent* pEvent );
private slots:
void Feedback( void );
// 鼠标事件需要
m_LastPos;
m_pCamera;
这里的GraphicsScene类保存的是来自view的Camera和一些信号以及事件的处理。在实现上也说一下它的构造函数吧。
GraphicsScene::GraphicsScene( QObject* pParent ):
QGraphicsScene( pParent ), m_pCamera( Q_NULLPTR )
ClickableTextItem* pTextItem = new ClickableTextItem( Q_NULLPTR );
pTextItem-&setPos( 10.0, 10.0 );
pTextItem-&setHtml( tr( &&font color=white&&
&Made By Jiangcaiyang&br&&
&Created in September&br&&
&Click for feedback.&
&&/font&& ) );
connect( pTextItem, SIGNAL( Clicked( ) ),
this, SLOT( Feedback( ) ) );
addItem( pTextItem );
ShaderOptionDialog* pDialog = new ShaderOptionDialog;
connect( pDialog, SIGNAL( SwitchShader( const QString& ) ),
this, SIGNAL( SwitchShader( const QString& ) ) );
connect( pDialog, SIGNAL( SetLightPos( const QVector3D& ) ),
this, SIGNAL( SetLightPos( const QVector3D& ) ) );
QGraphicsProxyWidget* pProxy = addWidget( pDialog, Qt::Window | Qt::WindowTitleHint );
pProxy-&setPos( 100, 200 );
我们创建了一个ClickableTextItem类,它继承于QGraphicsTextItem,它被摆在,显示三排可以点击的文字。随后添加了一个对话框,设置信号和槽完毕后就用代理放入场景中了。整个过程也是非常简单的。
我测试了下,整个程序在我的Ubuntu13.04下能够正常运行。只是由于显卡不同(Ubuntu下较难支持nvidia显卡,使用的是intel集显),specularOpt效果出不来。
> 本站内容系网友提交或本网编辑转载,其目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除内容!
将Qt.OpenGL.GLSL以及Qt的Graphics-View框架结合
九月份都快过去了,学生们也都开学了,我想校园也会热闹许多吧,在CSDN上也相应地热闹了一些.中秋节也过去了,自己身边还有很多没有吃完的月饼,于是将月饼作为早餐每天早上吃一个,希望这样不会浪费.
这个月的事情比较多,又比较忙,所以这么晚才能抽出时间写 ...
Qt应用程序之Application Main Window详解
下面的类提供了创建典型现代主窗口应用程序的所有事物,例如:主窗口自身,菜单以及工具栏,状态栏等等.
Qt 提供了下面的类用于管理主窗口以及与用户界面关联的组件: ...
原创不易,转载请注明出处:超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享 代码下载地址:/share/1568.htm 依赖注入,DI(Dependency Injection),它的作用自然不必多说,提及DI容器,例如spring,p ...
在&Qt Quick 事件处理之信号与槽&一文中介绍自定义信号时,举了一个简单的例子,定义了一个颜色选择组件,当用户在组建内点击鼠标时,该组件会发出一个携带颜色值的信号,当时我使用 Connections 对象连接到组件的 colorPicked 信号,改变文本的颜色. 当时用到的 Component . Loader 两个特性,一直没来 ...
详解web+maven+spring+mybatis+struts框架文件夹作用
1.程序名 2.Mybatis,mybatis是数据持久层,就是和对象类有关系的东西 3.存放java文件,xml,properties,java文件 4.JavaScript的类库 5.Deployed是部署的意思,部署后的文件,部署后自动生成,也就是放到tomcat上自 ...
学了很久的spring+mybatis+struts.一直都是单个的用他们,或者是两两组合用过,今天总算整合到一起了,配置起来有点麻烦,但是配置完一次之后,就轻松多了,那么框架整合配置详解如下. 1.导入相应的jar包 因为我们建造的是maven的web项目,所有我们在pom.xml中需要导入这些包. pom.xml 详细注释 &?xml versio ...
上一篇博客介绍了Xutils框架-HTTP使用详解,这里在介绍一下Xutils框架HTTP模块的内部代码. 按照我在项目中使用的顺序讲解下各个模块: 1.HttpUtils 这个是Xutils框架HTTP模块之中最主要的部分,首先在构造方法中对HTTP进行了各种配置,有connTimeout(连接超时),做多连接次数等. 下面定义的是HTTP的默认参数 pr ...
通过学习Vc++深入详解,加上vs提供的Call stack工具,总结出MFC框架的大致流程: 1.theApp的创建,这个对象是C..App的实例,它就是程序的句柄:HInstance对象. 2.WinMain:theApp作为参数传入与HInstance进行形实结合,实际调用AfxWinMain函数完成WinMain函
数的使命. 3.然后Af ...

我要回帖

更多关于 重写ontouchevent 的文章

 

随机推荐