鼠标控制模式用于三维空间可视化导航,通过鼠标的按键及少数键盘按键的组合,可以实现对三维视图的平移、缩放、选择等操作。
一、选择导航模式
由于之前使用过Blender,其鼠标的操作方式比较好用,因此这里使用Blender导航。Blender导航参照Blender的操作。以前需要SHIFT配合鼠标才能完成视图平移. 在2016年Blender增加了一个功能改变了这一情况。要平移视图,现在可以同时按下鼠标左键和鼠标右键并在视图中拖动。
在三维界面头文件中加入模式枚举,及添加鼠标操作相关成员:
//c3dwidget.h
class C3DWidget : public QWidget
{
......
protected:
//!三维场景转换模式
enum CurrentAction3d
{
CurAction3d_Nothing,
CurAction3d_DynamicPanning, //平移
CurAction3d_DynamicZooming, //缩放
CurAction3d_DynamicRotation //旋转
};
protected:
//!覆写键盘按键按下事件
void keyPressEvent(QKeyEvent *event);
//!覆写键盘按键释放事件
void keyReleaseEvent(QKeyEvent *event);
//!覆写鼠标按键按下事件
void mousePressEvent(QMouseEvent *event);
//!覆写鼠标按键释放事件
void mouseReleaseEvent(QMouseEvent *event);
//!覆写鼠标移动事件
void mouseMoveEvent(QMouseEvent *event);
//!覆写鼠标滚轮事件
void wheelEvent(QWheelEvent *event);
private:
Standard_Integer m_x_max; //!记录鼠标平移坐标X
Standard_Integer m_y_max; //!记录鼠标平移坐标Y
CurrentAction3d m_current_mode; //!三维场景转换模式
bool m_shift_key_pressed; //!记录Shift键是否被按下
......
};
二、平移
平移的方式有两种,通过if判断当前操作是否为平移方式的其中一种。其中一种需要加上SHIFT按键,则通过m_shift_key_pressed 变量判断SHIFT键是否被按下。
void C3DWidget::mousePressEvent(QMouseEvent *event)
{
if( ((event->buttons() & Qt::MidButton) && (QApplication::keyboardModifiers()==Qt::ShiftModifier) ) //平移方式1
||((event->buttons()&Qt::LeftButton)&&(event->buttons()&Qt::RightButton)))//平移方式2
{
m_current_mode = CurAction3d_DynamicPanning;
m_x_max = event->pos().x(); //记录起始X位置
m_y_max = event->pos().y(); //记录起始Y位置
}
......
}
void C3DWidget::mouseReleaseEvent(QMouseEvent *)
{
m_current_mode = CurAction3d_Nothing;
}
void C3DWidget::mouseMoveEvent(QMouseEvent *event)
{
switch (m_current_mode)
{
case CurAction3d_DynamicPanning:
//执行平移
m_view->Pan(event->pos().x() - m_x_max, m_y_max - event->pos().y());
m_x_max = event->pos().x();
m_y_max = event->pos().y();
break;
......
}
}
三、缩放
缩放通过V3d_View类的Zoom方法实现,Zoom方法的设计是通过相邻两次鼠标位置判断缩小或放大,以及缩放的程度。前两个参数为第一次鼠标的位置,后两个参数为第二次鼠标的位置。而滚动鼠标滚轮会Qt的wheelEvent事件,向上滚动和向下滚动event->angleDelta().y()会返回或正或负的数值,将此值模拟第二次鼠标的位置,实现三维界面缩放功能。
void C3DWidget::wheelEvent(QWheelEvent *event)
{
m_view->Zoom(0, 0, event->angleDelta().y(), 0); //执行缩放
}
5月9日更新:原来的程序只在固定点缩放,作以下更改后,缩放跟随鼠标的位置进行。
void C3DWidget::wheelEvent(QWheelEvent *event)
{
m_view->StartZoomAtPoint(event->pos().x(),event->pos().y());
m_view->ZoomAtPoint(0, 0, event->angleDelta().y(), 0); //执行缩放
}
四、旋转
鼠标的中键按下时,通过V3d_View类的StartRotation方法记录起始位置。鼠标发生移动后,使用Rotation方法实现三维界面旋转。
void C3DWidget::mousePressEvent(QMouseEvent *event)
{
if(......)//平移
{......}
else if(event->buttons() & Qt::MidButton) //旋转
{
m_current_mode = CurAction3d_DynamicRotation;
m_view->StartRotation(event->pos().x(), event->pos().y());
}
......
}
void C3DWidget::mouseMoveEvent(QMouseEvent *event)
{
switch (m_current_mode)
{
......
case CurAction3d_DynamicRotation:
//执行旋转
m_view->Rotation(event->pos().x(), event->pos().y());
break;
......
}
}