Open CASCADE+Qt:实现以鼠标为锚点缩放、平移、旋转
Open CASCADE+Qt:实现以鼠标为锚点缩放、平移、旋转 - 知乎
简介
本文实现在三维窗口中添加一个立方体,并实现以鼠标为锚点视图缩放、平移、旋转操作,效果见如下动图:

添加立方体
基于前面建立的三维窗口:
在OCCWidget
构造函数末尾,添加立方体,并将其添加到上下文中显示该立方体(绘制立方体不是本文重点):
OCCWidget::OCCWidget(QWidget *parent)
: QWidget{parent}
, m_dpiScale{this->devicePixelRatioF()}
{
...
// 绘制立方体
TopoDS_Shape box = BRepPrimAPI_MakeBox(100, 100, 100);
Handle(AIS_Shape) box_AIS = new AIS_Shape(box);
m_context->Display(box_AIS, Standard_True);
}
显示效果如下:

可以看到在画面中央,出现了我们绘制的立方体,默认立方体以边显示,没有显示面,并且默认视角为等轴测视角。
视图缩放、平移、旋转实现
这里鼠标实现视图的缩放、平移以及旋转操作详细描述为:当鼠标滚轮向前滚动时,视图放大,反之视图缩小;按下鼠标右键不放并移动鼠标,视图跟随鼠标移动而平移;按下鼠标中键不放并移动鼠标,视图跟随鼠标移动而旋转。上述事件包含:鼠标滚动事件、鼠标右键按下事件、鼠标中键按下事件以及鼠标移动事件,因此,要实现视图缩放、平移、以及旋转操作,需要重写以下鼠标事件:
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
分表为鼠标按下、释放、移动以及滚轮滚动事件。
鼠标按下事件中,当按下的为右键时,模式m_mode
赋值为平移Action3d_Panning
,并将点击位置的初始坐标赋值给m_x
和m_y
,以便在鼠标移动事件中,实现视图平移;当按下的为中键时,模式m_mode
赋值为平移Action3d_Rotation
,并调用m_view
成员函数StartRotation
函数以当前中键按下的点为初始点,开始旋转。
void OCCWidget::mousePressEvent(QMouseEvent* event){
//平移 鼠标右键
if ((event->buttons() & Qt::RightButton))
{
m_mode = Action3d_Panning;
m_x = event->pos().x();
m_y = event->pos().y();
}
//旋转 鼠标中键
else if (event->buttons() & Qt::MiddleButton)
{
m_mode = Action3d_Rotation;
m_view->StartRotation(m_dpiScale*event->pos().x(), m_dpiScale*event->pos().y());
}
}
鼠标移动事件中,判断m_mode
的模式,当为平移模式Action3d_Panning
时,调用m_view
成员函数Pan
平移视图;当为旋转模式Action3d_Rotation
时,调用m_view
成员函数Rotation
旋转视图。
void OCCWidget::mouseMoveEvent(QMouseEvent* event){
switch (m_mode)
{
case OCCWidget::Action3d_Panning:
m_view->Pan(m_dpiScale*(event->pos().x() - m_x), m_dpiScale*(m_y - event->pos().y()));
m_x = event->pos().x();
m_y = event->pos().y();
break;
case OCCWidget::Action3d_Rotation:
m_view->Rotation(m_dpiScale*event->pos().x(), m_dpiScale*event->pos().y());
break;
default:
break;
}
};
鼠标滚轮滚动事件中,通过鼠标滚轮滚动事件event
的成员函数angleDelta().y()
的值来判断鼠标滚轮滚动方向,该值为正时,表示滚轮向前滚动,值为负时表示滚轮向后滚动。m_view
调用成员函数StartZoomAtPoint
设置缩放锚点,即当前鼠标所在位置,而后调用ZoomAtPoint
实现缩放。
void OCCWidget::wheelEvent(QWheelEvent* event){
double aFactor = 5;
double aX = event->position().x();
double aY = event->position().y();
if (event->angleDelta().y() > 0)
{
aX += aFactor;
aY += aFactor;
}
else
{
aX -= aFactor;
aY -= aFactor;
}
m_view->StartZoomAtPoint(m_dpiScale*event->position().x(), m_dpiScale*event->position().y());
m_view->ZoomAtPoint(event->position().x(), event->position().y(), aX, aY);
};
最后补充鼠标释放事件:
void OCCWidget::mouseReleaseEvent(QMouseEvent* event){
m_mode = Action3d_Nothing;
}
显示器缩放比
需要注意的是,在实现上述成员函数过程中,例如视图平移操作中m_view->Pan(m_dpiScale*(event->pos().x() - m_x), m_dpiScale*(m_y - event->pos().y()));
其中m_dpiScale
表示显示器缩放比,默认显示器缩放比为100%,但对于高分辨率显示器,默认缩放比使得桌面图标以及文字过小,并不舒适,此时往往会更改显示器缩放比,当显示器缩放比不为100%时,若调用m_view->Pan(event->pos().x() - m_x, m_y - event->pos().y());
那么平移将出现异常。
源码
源码见:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2023-01-16 c# ?的用法