#include <OpenGl_GraphicDriver.hxx>
#include "view.h"
#include <QMenu>
#include <QMouseEvent>
#include <QRubberBand>
#include <QStyleFactory>
#include <V3d_View.hxx>
#include <Aspect_Handle.hxx>
#include <Aspect_DisplayConnection.hxx>
#ifdef WNT//判断你的系统并做出相应处理
#include <WNT_Window.hxx>
#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
#include <Cocoa_Window.hxx>
#else
#undef Bool
#undef None
#undef KeyPress
#undef KeyRelease
#undef FocusOut
#undef FontChange
#include <Xw_Window.hxx>
#endif
static Handle(Graphic3d_GraphicDriver)& GetGraphicDriver()//Graphic3d_GraphicDriver是一个3D图形驱动程序,用于在计算机上渲染和操作三维图形。它是连接3D图形应用程序和计算机图形硬件的桥梁,允许开发者利用计算机图形硬件的能力进行高效的3D渲染。
//Graphic3d_GraphicDriver通常与3D图形库或引擎一起使用,例如OpenGL、DirectX或Unity等。开发者可以使用这些库或引擎来创建和管理3D图形应用程序,并通过Graphic3d_GraphicDriver与计算机图形硬件进行交互,以实现高效的3D渲染。
{
static Handle(Graphic3d_GraphicDriver) aGraphicDriver;
return aGraphicDriver;
}
OccView::OccView(QWidget* parent)
: QWidget(parent),
myXmin(0),//相当于int myxmin=0;注释掉了也没有影响,修改也不影响啥
myYmin(0),
myXmax(0),
myYmax(0),
myCurrentMode(CurAction3d_DynamicRotation),//CurAction3d_DynamicRotation是一个动作捕捉相关的功能,用于实现3D动态旋转。即使你不使用旋转的那个命令也一样能旋转图形
myDegenerateModeIsOn(Standard_True),//和上面一个都是currentaction3d的枚举,都有各自的3d作用,Standard_True就相当于true。注释掉好像也不影响
myRectBand(NULL)//来自于一个qt类,它提供了一种方便的方法来在图形界面中显示橡皮筋效果。注释掉后也没有啥影响
{
// No Background
setBackgroundRole(QPalette::NoRole);//setBackgroundRole是Qt中的一个函数,其作用是设置qbrush部件的背景颜色。注释掉好像也不影响
// set focus policy to threat QContextMenuEvent from keyboard
setFocusPolicy(Qt::StrongFocus);//setFocusPolicy函数在Qt中用于设置部件获得焦点的方式。部件获得焦点的作用主要是接收用户的键盘输入。
//当一个部件获得焦点时,它会成为键盘输入的主要接收者。例如,如果一个文本框获得焦点,用户就可以在其中输入文本。类似地,如果一个按钮获得焦点,用户可以通过按下空格键或回车键来触发该按钮的操作,这与使用鼠标点击该按钮是相同的效果。
// 在图形用户界面中,通过键盘操作可以大大提高用户的效率。因此,合理地设置和管理部件的焦点是非常重要的。注释掉后也不影响。
//Qt中有以下几种获得焦点的方式:
// Qt::TabFocus:通过Tab键获得焦点。
// Qt::ClickFocus:通过被单击获得焦点。
// Qt::StrongFocus:可通过以上两种方式获得焦点。
// Qt::NoFocus:不能通过以上两种方式获得焦点。
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
//在Qt中,setAttribute函数用于设置窗口部件的属性。Qt::WA_PaintOnScreen和Qt::WA_NoSystemBackground是Qt中预定义的窗口部件属性。
/* setAttribute(Qt::WA_PaintOnScreen); 这个属性的作用是关闭窗口部件的双缓冲绘图。通常情况下,Qt的所有窗口部件默认都使用双缓冲进行绘图,这样可以减轻绘制的闪烁感。但在某些情况下,用户可能需要关闭双缓冲,自己管理绘图。关闭双缓冲后,所有的绘图操作将直接在屏幕上进行。
setAttribute(Qt::WA_NoSystemBackground); 这个属性的作用是禁止窗口部件使用系统背景。默认情况下,窗口部件会使用系统的背景颜色和样式。但如果你希望窗口部件有一个自定义的背景,或者根本不想让它有背景,就可以设置这个属性。
请注意,这两个属性是互斥的,也就是说,如果一个窗口部件同时设置了这两个属性,那么Qt::WA_PaintOnScreen将覆盖Qt::WA_NoSystemBackground,窗口部件将不会有背景。*/
// Enable the mouse tracking, by default the mouse tracking is disabled.
setMouseTracking(true);//注释掉好像也不影响
//在 PyQt5 中,setMouseTracking() 是 QWidget 类中的一个方法,用于设置一个组件是否跟踪鼠标移动事件。具体作用如下:
/* 当一个组件启用了鼠标移动跟踪,它会在鼠标移动时接收 mouseMoveEvent() 事件,并能够响应这些事件。
如果一个组件没有启用鼠标移动跟踪,它只有在鼠标按钮按下或释放时才会接收鼠标事件。
默认情况下,QWidget 类中的组件都没有启用鼠标移动跟踪,这意味着它们只有在鼠标按钮按下或释放时才会接收鼠标事件。
如果你想在鼠标移动时接收鼠标事件,可以使用 setMouseTracking(True) 方法来启用鼠标移动跟踪。然后,可以通过重写 mouseMoveEvent() 方法,在鼠标移动时输出鼠标的坐标信息。
总的来说,setMouseTracking(true) 可以让程序在鼠标移动时实时接收并处理鼠标事件。*/
init();
}
void OccView::init()//成员函数可以在类外面定义
{
// Create Aspect_DisplayConnection
Handle(Aspect_DisplayConnection) aDisplayConnection = new Aspect_DisplayConnection();
//Aspect_DisplayConnection是Qt中的一个类,用于表示窗口部件和显示设备之间的连接。它的主要作用是在窗口部件和显示设备之间建立一个桥梁,使得窗口部件能够在正确的显示设备上绘制自己。
//在Qt中,窗口部件并不知道自己将在哪个显示设备上绘制,也不知道显示设备的分辨率和其他属性。而Aspect_DisplayConnection类则封装了这些信息,使得窗口部件可以通过它与显示设备进行交互。
// Aspect_DisplayConnection类还提供了一些方法,用于获取显示设备的属性,如分辨率、色彩深度等。此外,它还可以处理窗口部件和显示设备之间的缩放和旋转等操作,以保证窗口部件在不同的显示设备上都能够正确地显示。
// 总的来说,Aspect_DisplayConnection类在Qt的窗口系统中扮演着一个非常重要的角色,它使得窗口部件能够在不同的显示设备上正确地绘制自己,并且处理各种显示设备的属性。
// Get graphic driver if it exists, otherwise initialise it
if (GetGraphicDriver().IsNull())
{
GetGraphicDriver() = new OpenGl_GraphicDriver(aDisplayConnection);//OpenGl_GraphicDriver是一个图形驱动程序,用于在计算机上渲染和操作三维图形。
}
// Get window handle. This returns something suitable for all platforms.
WId window_handle = (WId)winId();//总的来说,这行代码的目的是获取一个 Qt 窗口部件的本地窗口句柄,并将其存储在一个变量中以备后用。后面的代码根据不同的平台(Windows、macOS、其他)使用这个句柄来创建相应的窗口对象。
// Create appropriate window for platform
#ifdef WNT 根据不同的平台创建不同的窗口对象,这里使用了条件编译
Handle(WNT_Window) wind = new WNT_Window((Aspect_Handle)window_handle);
#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
Handle(Cocoa_Window) wind = new Cocoa_Window((NSView*)window_handle);
#else
Handle(Xw_Window) wind = new Xw_Window(aDisplayConnection, (Window)window_handle);
#endif
// Create V3dViewer and V3d_View
myViewer = new V3d_Viewer(GetGraphicDriver());//注释会报错,但不是语法错误
myView = myViewer->CreateView();//CreateView() 方法在 OpenCASCADE Technology 中用于创建一个新的三维视图对象,以便在应用程序中显示和操作三维模型。
//使用 myViewer 对象的 CreateView() 方法创建一个 V3d_View 对象,并将其赋值给 myView 变量
myView->SetWindow(wind);//SetWindow() 方法通常用于激活视图类中与屏幕建立映射的窗口。这个方法是在 V3d_View 类中定义的,该类用于管理和渲染三维场景。
if (!wind->IsMapped()) wind->Map();//IsMapped()是Qt库中的一个函数,主要用于判断窗口部件(QWidget)是否已经被映射到屏幕上。如果没有映射,这里会让你再映射,所以按道理来说,把它注释掉也可以运行
// Create AISInteractiveContext
myContext = new AIS_InteractiveContext(myViewer);
//AIS_InteractiveContext是OpenCASCADECommunity(OCC)中的一种交互式场景,用于管理和显示3D场景中的对象。在AIS_InteractiveContext中,shiftselect是一种特殊的多选模式,它允许用户选择多个实体。当用户按住Shift键并单击多个实体时,AIS_InteractiveContext会将这些实体添加到当前选择集中,而不是替换当前选择集中的实体。这意味着,如果需要选择多个实体来执行操作(例如剪切、移动或旋转),则可以使用shiftselect。
//此外,AIS_InteractiveContext还有一个函数DisplayNoSelection,其主要作用是在绘图上下文中显示一个不可选择的交互对象。
// Set up lights etc
myViewer->SetDefaultLights();
myViewer->SetLightOn();
myView->SetBackgroundColor(Quantity_NOC_BLACK);//绘图界面的背景颜色
myView->MustBeResized();//MustBeResized()是OpenCASCADE Technology(OCCT)中的一个方法,通常用于判断3D视图是否需要重新调整大小。这个方法是在V3d_View类中定义的,该类用于管理和渲染三维场景。
myView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, 0.08, V3d_ZBUFFER);//坐标系的显示
myContext->SetDisplayMode(AIS_Shaded, Standard_True);
}
const Handle(AIS_InteractiveContext)& OccView::getContext() const
{
return myContext;
}
/*!
Get paint engine for the OpenGL viewer. [ virtual public ]
*/
QPaintEngine* OccView::paintEngine() const
{
return 0;
}
void OccView::paintEvent(QPaintEvent* /*theEvent*/)
{
myView->Redraw();// 调用 myView 的 Redraw 方法,重绘视图内容
}
void OccView::resizeEvent(QResizeEvent* /*theEvent*/)// 重写 QWidget 类的 resizeEvent 函数,当窗口大小被改变时,该函数会被调用。
{
if (!myView.IsNull())
{
myView->MustBeResized();
}
}
// 函数 fitAll,将视图中的所有内容完全适应窗口,并重绘视图
void OccView::fitAll(void)//注释掉后,没法直接fitall了。对应lzzcad里的槽函数
{
myView->FitAll();
myView->ZFitAll();
myView->Redraw();
}
void OccView::reset(void)//注释掉后,没法直接reset了。对应lzzcad里的槽函数
{
myView->Reset();
}
void OccView::pan(void)//注释掉后,没法直接pan了。对应lzzcad里的槽函数
{
myCurrentMode = CurAction3d_DynamicPanning;
}
void OccView::zoom(void)//注释掉后,没法直接zoom了。对应lzzcad里的槽函数
{
myCurrentMode = CurAction3d_DynamicZooming;
}
void OccView::rotate(void)//注释掉后,没法直接rotate了。对应lzzcad里的槽函数
{
myCurrentMode = CurAction3d_DynamicRotation;
}
void OccView::mousePressEvent(QMouseEvent* theEvent)//按压鼠标的判定
{
if (theEvent->button() == Qt::LeftButton)// 检查点击的鼠标按钮是否为左键
{
onLButtonDown((theEvent->buttons() | theEvent->modifiers()), theEvent->pos());//buttons()这个函数似乎是为了提供一个方法来检索鼠标按钮的当前状态。modifiers()这个函数似乎是为了提供一个方法来检索键盘修饰符的当前状态
}//pos()这个函数似乎是为了提供一个方法来检索某个图形对象(如线段或矩形)的起始点或位置
else if (theEvent->button() == Qt::MidButton)// 检查点击的鼠标按钮是否为中键
{
onMButtonDown((theEvent->buttons() | theEvent->modifiers()), theEvent->pos());
}
else if (theEvent->button() == Qt::RightButton)// 检查点击的鼠标按钮是否为右键
{
onRButtonDown((theEvent->buttons() | theEvent->modifiers()), theEvent->pos());
}
}
void OccView::mouseReleaseEvent(QMouseEvent* theEvent)//松开鼠标的判定
{
if (theEvent->button() == Qt::LeftButton)
{
onLButtonUp(theEvent->buttons() | theEvent->modifiers(), theEvent->pos());
}
else if (theEvent->button() == Qt::MidButton)
{
onMButtonUp(theEvent->buttons() | theEvent->modifiers(), theEvent->pos());
}
else if (theEvent->button() == Qt::RightButton)
{
onRButtonUp(theEvent->buttons() | theEvent->modifiers(), theEvent->pos());
}
}
void OccView::mouseMoveEvent(QMouseEvent* theEvent)//鼠标移动。这段代码的作用是在鼠标移动时调用自定义的 onMouseMove 函数,并将鼠标按钮状态和位置作为参数传递,以便执行特定的操作或响应。
{
onMouseMove(theEvent->buttons(), theEvent->pos());
}
void OccView::wheelEvent(QWheelEvent* theEvent)//这个函数似乎是为了处理鼠标滚轮事件。当用户在OccView对象上滚动鼠标滚轮时,它会调用onMouseWheel函数,并传递鼠标按钮状态、滚动量和鼠标位置作为参数。
{
onMouseWheel(theEvent->buttons(), theEvent->delta(), theEvent->pos());
}
//下面开始是具体函数的方法
void OccView::onLButtonDown(const int /*theFlags*/, const QPoint thePoint)//这段代码是 Qt 框架中的一个鼠标左键按下事件处理函数。注释掉好像也不影响,因为这里没什么左键操作的东西
{//注释掉还是有影响的,在你选中东西后鼠标离开,标记就消失了
// Save the current mouse coordinate in min.
myXmin = thePoint.x();
myYmin = thePoint.y();
myXmax = thePoint.x();
myYmax = thePoint.y();
}
void OccView::onMButtonDown(const int /*theFlags*/, const QPoint thePoint)//这段代码是 Qt 框架中的一个鼠标中键按下事件处理函数。注释掉会影响,每次旋转的时候位置会改变
{
// Save the current mouse coordinate in min.
myXmin = thePoint.x();
myYmin = thePoint.y();
myXmax = thePoint.x();
myYmax = thePoint.y();
if (myCurrentMode == CurAction3d_DynamicRotation)// 检查当前模式是否为动态旋转模式
{
myView->StartRotation(thePoint.x(), thePoint.y()); // 如果是,则开始旋转操作,传入当前鼠标的 x 和 y 坐标
}
}
void OccView::onRButtonDown(const int /*theFlags*/, const QPoint /*thePoint*/)//这段代码是 Qt 框架中的一个鼠标右键按下事件处理函数,感觉没什么用,也可以加上跟左键一样的东西
{
//这意味着,虽然函数可以接受这些参数,但在函数体内无法直接使用它们。这可能是为了避免编译错误或警告,或者是因为这个函数尚未实现或暂时不需要使用这些参数。
}
void OccView::onMouseWheel(const int /*theFlags*/, const int theDelta, const QPoint thePoint)//一个鼠标滚轮事件处理函数,注释后没法用滚轮放大缩小了
{//theDelta表示滚轮滚动的数量和方向
Standard_Integer aFactor = 16;//Standard_Integer相当于int
Standard_Integer aX = thePoint.x();
Standard_Integer aY = thePoint.y();
if (theDelta > 0)
{
aX += aFactor;
aY += aFactor;
}
else
{
aX -= aFactor;
aY -= aFactor;
}
myView->Zoom(thePoint.x(), thePoint.y(), aX, aY); // 调用myView对象的Zoom方法,对指定位置进行缩放操作。方法四个参数分别为:原始鼠标点击位置的x和y坐标,以及经过滚轮滚动操作后的鼠标点击位置的x和y坐标
}
void OccView::addItemInPopup(QMenu* /*theMenu*/)//这段代码是 Qt 框架中的一个函数,用于向弹出菜单(上下文菜单)中添加项。
{
}
void OccView::popup(const int /*x*/, const int /*y*/)//定义一个名为OccView的类中的弹出菜单处理函数
{
}
void OccView::onLButtonUp(const int theFlags, const QPoint thePoint)//是一个处理鼠标左键释放事件的函数
{
// Hide the QRubberBand
if (myRectBand)
{
myRectBand->hide();
}
// Ctrl for multi selection.
if (thePoint.x() == myXmin && thePoint.y() == myYmin)
{
if (theFlags & Qt::ControlModifier)
{
multiInputEvent(thePoint.x(), thePoint.y());//按了crtl就可以多选,否则就是单选,注释掉就永远是单选了
}
else
{
inputEvent(thePoint.x(), thePoint.y());
}
}
}
void OccView::onMButtonUp(const int /*theFlags*/, const QPoint thePoint)//是一个处理鼠标中键释放事件的函数
{
if (thePoint.x() == myXmin && thePoint.y() == myYmin)
{
panByMiddleButton(thePoint);
}
}
void OccView::onRButtonUp(const int /*theFlags*/, const QPoint thePoint)//是一个处理鼠标右键释放事件的函数
{
popup(thePoint.x(), thePoint.y());
}
void OccView::onMouseMove(const int theFlags, const QPoint thePoint)//是一个处理鼠标移动事件的函数
{
// Draw the rubber band.
if (theFlags & Qt::LeftButton)//在函数体内,theFlags参数被用来检查鼠标按键的状态,以便执行相应的操作。
{
drawRubberBand(myXmin, myYmin, thePoint.x(), thePoint.y());
dragEvent(thePoint.x(), thePoint.y());
}
// Ctrl for multi selection.
if (theFlags & Qt::ControlModifier)
{
multiMoveEvent(thePoint.x(), thePoint.y());
}
else
{
moveEvent(thePoint.x(), thePoint.y());
}
// Middle button.
if (theFlags & Qt::MidButton)
{
switch (myCurrentMode)
{
case CurAction3d_DynamicRotation:
myView->Rotation(thePoint.x(), thePoint.y());
break;
case CurAction3d_DynamicZooming:
myView->Zoom(myXmin, myYmin, thePoint.x(), thePoint.y());
break;
case CurAction3d_DynamicPanning:
myView->Pan(thePoint.x() - myXmax, myYmax - thePoint.y());
myXmax = thePoint.x();
myYmax = thePoint.y();
break;
default:
break;
}
}
}
void OccView::dragEvent(const int x, const int y)//一个处理拖动事件的函数
{
myContext->Select(myXmin, myYmin, x, y, myView, Standard_True);
emit selectionChanged();//selectionChanged函数的作用是在选择发生改变时激活OccView对象的指定信号。这通常用于触发一些响应选择改变的操作或更新界面状态。
}
void OccView::multiDragEvent(const int x, const int y)//一个处理多重拖动事件的函数
{
myContext->ShiftSelect(myXmin, myYmin, x, y, myView, Standard_True);
emit selectionChanged();
}
void OccView::inputEvent(const int x, const int y)//是一个处理输入事件的函数,注释掉也不影响
{
Q_UNUSED(x);
Q_UNUSED(y);
myContext->Select(Standard_True);
emit selectionChanged();
}
void OccView::multiInputEvent(const int x, const int y)//是一个处理多重输入事件的函数,注释掉也不影响
{
Q_UNUSED(x);
Q_UNUSED(y);
myContext->ShiftSelect(Standard_True);
emit selectionChanged();
}
void OccView::moveEvent(const int x, const int y)//是一个处理移动事件的函数
{
myContext->MoveTo(x, y, myView, Standard_True);
}
void OccView::multiMoveEvent(const int x, const int y)//是一个处理多重移动事件的函数
{
myContext->MoveTo(x, y, myView, Standard_True);
}
void OccView::drawRubberBand(const int minX, const int minY, const int maxX, const int maxY)//是一个绘制橡皮筋线的函数,注释掉也不影响
{
QRect aRect;
// Set the rectangle correctly.
(minX < maxX) ? (aRect.setX(minX)) : (aRect.setX(maxX));
(minY < maxY) ? (aRect.setY(minY)) : (aRect.setY(maxY));
aRect.setWidth(abs(maxX - minX));
aRect.setHeight(abs(maxY - minY));
if (!myRectBand)
{
myRectBand = new QRubberBand(QRubberBand::Rectangle, this);
// setStyle is important, set to windows style will just draw
// rectangle frame, otherwise will draw a solid rectangle.
myRectBand->setStyle(QStyleFactory::create("windows"));
}
myRectBand->setGeometry(aRect);
myRectBand->show();
}
void OccView::panByMiddleButton(const QPoint& thePoint)//是一个处理鼠标中键按下事件的函数,用于平移视图。注释掉好像也不影响
{
Standard_Integer aCenterX = 0;
Standard_Integer aCenterY = 0;
QSize aSize = size();
aCenterX = aSize.width() / 2;
aCenterY = aSize.height() / 2;
myView->Pan(aCenterX - thePoint.x(), thePoint.y() - aCenterY);
}
occview.cpp新注释
最新推荐文章于 2024-08-11 09:20:04 发布