当前位置: 首页 > news >正文

Qt3D--箭头示例

程序运行效果图:

以上效果图使用Qt原生控件,没有对控件进行QSS设置,下面有源码,你可以在mainwindow.cpp中对控件进行样式设置。

该工程用的是Qt6进行开发 使用C++语言 用CMake进行构建工程。

代码讲解可能不太详细或者有兴趣再加,首先了解Qt3D进行开发时,相关类的作用。该工程为你提供参考示例。

箭头讲解:

箭头源码:

arrowentity.h

#ifndef ARROWENTITY_H
#define ARROWENTITY_H#include <QObject>
#include <QWidget>
#include <QDebug>
#include <QTimer>
#include <QColor>
#include <QColorDialog>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DRender/QCamera>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DExtras/QPlaneMesh>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QPointLight>
#include <Qt3DRender/QDirectionalLight>
#include <Qt3DExtras/QForwardRenderer>
#include <Qt3DExtras/QCylinderMesh>
#include <Qt3DExtras/QConeMesh>#include <QVector3D>struct ArrowSize{double cyLen_ = 1;double conLen_ = 1;double cyR_ = 1;double conR_ = 1;
public:ArrowSize(){}ArrowSize(double cyLen,double cyR,double conLen,double conR):cyLen_(cyLen),cyR_(cyR),conLen_(conLen),conR_(conR){}
};class ArrowEntity : public Qt3DCore::QEntity
{Q_OBJECT
public:explicit ArrowEntity(Qt3DCore::QEntity* parent = nullptr);~ArrowEntity(){}//获取跟实体Qt3DCore::QEntity* getRootEntity();//重置视图按钮void ResetView();//设置箭头位置函数 ,输入位置QVector3Dvoid setArrowPosition(QVector3D& pos);//设置柱体 圆锥 的长度与最大半径 ,输入参数是大于0的double数值void setArrowLenAndRot(ArrowSize& sz);//设置圆柱体颜色 位置void setCylinderColorSelected(QColor& col);//设置圆锥体颜色 位置void setConeColorSelected(QColor& col);//获取圆柱颜色QColor getCyColor();//获取圆锥颜色QColor getConColor();
private://禁用拷贝构造 和 赋值重载ArrowEntity(ArrowEntity& arrow)=delete;ArrowEntity& operator=(ArrowEntity& arrow)=delete;//创建 圆柱体 圆锥体实体void createCylinderAndConeEntity();//物体自动旋转void updateRotation();public slots://自动旋转 -- 用定时器控制void onAutoRotateTimer(const QVector3D &eulerAngles);//通过滑杆控件 -- 控制物体旋转 x y z 速度void onXRotationChanged(int angle);void onYRotationChanged(int angle);void onZRotationChanged(int angle);void onRotationSpeedChanged(int speed);void onXDirect(const QString& x);void onYDirect(const QString& y);void onZDirect(const QString& z);private://颜色QColor cylinderColor;       //圆柱体颜色QColor coneColor;           //圆锥体颜色//长度 半径ArrowSize entitySz;//该对象可以设置 圆柱圆锥的长度半径//圆柱体 圆锥体实体 根实体// Qt3DCore::QEntity *rootEntity;              // 根实体Qt3DCore::QEntity *rootNextEntity;          //部分跟实体Qt3DCore::QEntity *cylinderEntity;          // 圆柱体实体Qt3DCore::QEntity *coneEntity;              // 圆锥体实体//物体旋转  x y z 速度QVector3D xyzRotation;int rotationSpeed = 2;//物体坐标QVector3D xyzPos = {0,0,0};//网格Qt3DExtras::QCylinderMesh* cylinder;Qt3DExtras::QConeMesh* cone;//材质 变换Qt3DCore::QTransform *partTransform;       // 模型局部变换--不包含上一层的任何实体Qt3DCore::QTransform *modelTransform;       // 模型整体变换Qt3DCore::QTransform *cylinderTransform;    // 圆柱体变换Qt3DCore::QTransform *coneTransform;        // 圆锥体变换Qt3DExtras::QPhongMaterial *cylinderMaterial; // 圆柱体材质Qt3DExtras::QPhongMaterial *coneMaterial;     // 圆锥体材质//自动旋转定时器QTimer* autoRotateTimer;
};#endif // ARROWENTITY_H

arrowentity.cpp

#include "arrowentity.h"#include <QSize>
#include <QScreen>ArrowEntity::ArrowEntity(Qt3DCore::QEntity* parent):Qt3DCore::QEntity(parent),cylinderEntity(nullptr),coneEntity(nullptr),modelTransform(nullptr),cylinderTransform(nullptr),coneTransform(nullptr),cylinderMaterial(nullptr),coneMaterial(nullptr)
{qDebug()<<"arrowentity";ArrowSize sz(2.0,0.5,3,1);entitySz = sz;createCylinderAndConeEntity();
}Qt3DCore::QEntity *ArrowEntity::getRootEntity()
{return this;
}void ArrowEntity::createCylinderAndConeEntity()
{//创建模型整体变换modelTransform = new Qt3DCore::QTransform();this->addComponent(modelTransform);//创建光源// Qt3DRender::QPointLight* light = new Qt3DRender::QPointLight();Qt3DRender::QDirectionalLight* light = new Qt3DRender::QDirectionalLight();// light->setIntensity(1.0f);// light->setColor("white");light->setColor(QColor(Qt::white));light->setIntensity(1.0f);light->setWorldDirection(QVector3D(-1, -1, -1));Qt3DCore::QTransform* lightTrans = new Qt3DCore::QTransform();lightTrans->setTranslation(QVector3D(10,10,20));//光源位置//光实体Qt3DCore::QEntity* lightEntity = new Qt3DCore::QEntity(this);lightEntity->addComponent(light);lightEntity->addComponent(lightTrans);rootNextEntity = new Qt3DCore::QEntity(this);partTransform = new Qt3DCore::QTransform();rootNextEntity->addComponent(partTransform);//创建圆柱实体cylinderEntity = new Qt3DCore::QEntity(rootNextEntity);//创建网格cylinder = new Qt3DExtras::QCylinderMesh();// cylinder->setLength(5.0f);  //长度// cylinder->setRadius(0.8f);  //半径cylinder->setLength(entitySz.cyLen_);  //长度cylinder->setRadius(entitySz.cyR_);  //半径cylinder->setRings(100);    //环数cylinder->setSlices(20);    //切片数//创建位置cylinderTransform = new Qt3DCore::QTransform();cylinderTransform->setTranslation(QVector3D(0, entitySz.cyLen_/2.0, 0));//创建材质cylinderMaterial = new Qt3DExtras::QPhongMaterial();cylinderMaterial->setDiffuse(QColor(QRgb(0x0055ff)));cylinderEntity->addComponent(cylinder);cylinderEntity->addComponent(cylinderTransform);cylinderEntity->addComponent(cylinderMaterial);//创建圆锥实体coneEntity = new Qt3DCore::QEntity(rootNextEntity);cone = new Qt3DExtras::QConeMesh();// cone->setRings(8);   //半径// cone->setLength(3.0f);  //长度cone->setBottomRadius(entitySz.conR_);   //半径cone->setLength(entitySz.conLen_);  //长度cone->setSlices(20);    //切片cone->setRings(200);    //环数//位置coneTransform = new Qt3DCore::QTransform();coneTransform->setTranslation(QVector3D(0, entitySz.cyLen_ + entitySz.conLen_/2.0, 0));//创建材质coneMaterial = new Qt3DExtras::QPhongMaterial();coneMaterial->setDiffuse(QColor(QRgb(0xff5500)));coneEntity->addComponent(cone);coneEntity->addComponent(coneTransform);coneEntity->addComponent(coneMaterial);}void ArrowEntity::updateRotation()
{// 设置模型的旋转,使用四元数避免万向锁问题modelTransform->setRotation(QQuaternion::fromEulerAngles(xyzRotation));
}void ArrowEntity::setCylinderColorSelected(QColor &col)
{cylinderMaterial->setDiffuse(col);
}void ArrowEntity::setConeColorSelected(QColor &col)
{coneMaterial->setDiffuse(col);
}// void ArrowEntity::onCylinderColorSelected()
// {
//     // QWidget* parentWidget = new QWidget();  // 创建临时QWidget
//     // QColor color = QColorDialog::getColor(cylinderMaterial->diffuse(), parentWidget, "选择圆柱体颜色");
//     // if (color.isValid()) {
//     //     cylinderMaterial->setDiffuse(color);
//     // }
//     // delete parentWidget;
//     cylinderMaterial->setDiffuse(color);
// }// void ArrowEntity::onConeColorSelected()
// {
//     // QWidget* parentWidget = new QWidget();  // 创建临时QWidget
//     // QColor color = QColorDialog::getColor(coneMaterial->diffuse(), parentWidget, "选择圆锥体颜色");
//     // if (color.isValid()) {
//     //     coneMaterial->setDiffuse(color);
//     // }
//     // delete parentWidget;
//     coneMaterial->setDiffuse(color);
// }void ArrowEntity::onAutoRotateTimer(const QVector3D &eulerAngles)
{// // 初始化自动旋转定时器// autoRotateTimer = new QTimer(this);// connect(autoRotateTimer, &QTimer::timeout, [this]() {//     // 自动旋转逻辑 - 同时绕三个轴旋转,速度由rotationSpeed控制//     xRotation += 0.5f * rotationSpeed;//     yRotation += 0.3f * rotationSpeed;//     zRotation += 0.2f * rotationSpeed;//     // 确保角度在0-360之间//     if (xRotation >= 360) xRotation -= 360;//     if (yRotation >= 360) yRotation -= 360;//     if (zRotation >= 360) zRotation -= 360;// QVector3D xyzRotation(xRotation,yRotation,zRotation);// //     updateRotation();//     // 更新滑块位置//     QSlider* xSlider = findChild<QSlider*>();//     if (xSlider) xSlider->setValue(static_cast<int>(xRotation));// });
}void ArrowEntity::onXRotationChanged(int angle)
{xyzRotation.setX(angle);updateRotation();
}void ArrowEntity::onYRotationChanged(int angle)
{xyzRotation.setY(angle);updateRotation();
}void ArrowEntity::onZRotationChanged(int angle)
{xyzRotation.setZ(angle);updateRotation();
}void ArrowEntity::onRotationSpeedChanged(int speed)
{rotationSpeed = speed;
}void ArrowEntity::onXDirect(const QString &x)
{qDebug()<<"ArrowEntity::onXDirect";// cylinderTransform->setRotation(QQuaternion::fromEulerAngles(QVector3D(x.toDouble(),1,1)));// coneTransform->setRotation(QQuaternion::fromEulerAngles(QVector3D(x.toDouble(),1,1)));partTransform->setRotation(QQuaternion::fromEulerAngles(QVector3D(x.toDouble(),1,1)));
}void ArrowEntity::onYDirect(const QString &y)
{partTransform->setRotation(QQuaternion::fromEulerAngles(QVector3D(1,y.toDouble(),1)));
}void ArrowEntity::onZDirect(const QString &z)
{partTransform->setRotation(QQuaternion::fromEulerAngles(QVector3D(1,1,z.toDouble())));
}void ArrowEntity::ResetView()
{xyzRotation.setX(0);xyzRotation.setY(0);xyzRotation.setZ(0);updateRotation();
}void ArrowEntity::setArrowPosition(QVector3D &pos)
{xyzPos = pos;modelTransform->setTranslation(xyzPos);
}void ArrowEntity::setArrowLenAndRot(ArrowSize& sz)
{if(sz.cyLen_>0){entitySz.cyLen_ = sz.cyLen_;}if(sz.conLen_>0){entitySz.conLen_ = sz.conLen_;}if(sz.cyR_>0){entitySz.cyR_ = sz.cyR_;}if(sz.conR_>0){entitySz.conR_ = sz.conR_;}if(sz.cyLen_>0||sz.conLen_>0||sz.cyR_>0||sz.conR_>0){// entitySz = sz;cylinder->setLength(entitySz.cyLen_);  //长度cylinder->setRadius(entitySz.cyR_);  //半径cylinder->setRings(100); // 保持网格精度一致cylinder->setSlices(20);// cylinder->setEnabled(false);// cylinderTransform->setTranslation(QVector3D(0,0,0)+xyzPos);cylinderTransform->setTranslation(QVector3D(0,entitySz.cyLen_/2.0,0));cone->setBottomRadius(entitySz.conR_);   //半径cone->setLength(entitySz.conLen_);  //长度cone->setRings(200);                   // 保持网格精度cone->setSlices(20);// qDebug()<<entitySz.cyLen_/2.0 + entitySz.conLen_/2.0;coneTransform->setTranslation(QVector3D(0,entitySz.cyLen_/*/2.0*/ + entitySz.conLen_/2.0,0));}
}QColor ArrowEntity::getCyColor()
{return cylinderMaterial->diffuse();
}
QColor ArrowEntity::getConColor()
{return coneMaterial->diffuse();
}

坐标轴讲解:

坐标轴源码:

coordinateaxis.h

#ifndef COORDINATEAXIS_H
#define COORDINATEAXIS_H#include <QWidget>
#include <QObject>
#include <Qt3DCore/QEntity>
#include <Qt3DExtras/QCylinderMesh>
#include <Qt3DExtras/QConeMesh>
#include <QColor>
#include <QColorDialog>
#include <QSize>
#include <QVector3D>
#include <QDebug>struct AxisSize{double cyLen_ = 1;double conLen_ = 1;double cyR_ = 1;double conR_ = 1;
public:AxisSize(){}AxisSize(double cyLen,double cyR,double conLen,double conR):cyLen_(cyLen),cyR_(cyR),conLen_(conLen),conR_(conR){}// AxisSize& operator=(AxisSize& axSz)// {//     if(*this != axSz)//     {//         conLen_ = axSz.conLen_;//         conR_ = axSz.conR_;//         cyLen_ = axSz.cyLen_;//         cyR_ = axSz.cyR_;//     }//     return *this;// }// bool operator!=(AxisSize& axSz)// {//     return *this == axSz;// }// bool operator==(AxisSize& axSz)// {//     if(conLen_ == axSz.conLen_&&conR_ == axSz.conR_&&//         cyLen_ == axSz.cyLen_&&cyR_ == axSz.cyR_)//         return true;//     else//         return false;// }
};class CoordinateAxis : public Qt3DCore::QEntity
{Q_OBJECT
public:CoordinateAxis(Qt3DCore::QEntity* parent = nullptr):Qt3DCore::QEntity(parent),m_rootEntity(new Qt3DCore::QEntity(parent)){AxisSize ax(7.0,0.05,0.5,0.1);axSz = ax;createAxis(7.0f);}void createAxis(double length);Qt3DCore::QEntity* getAxisEntity() const;
private:Qt3DCore::QEntity* createSingleAxis(double length, const QVector3D& direction,const QColor& color);
private:Qt3DCore::QEntity* m_rootEntity = nullptr;double m_axisLength;AxisSize axSz;
};#endif // COORDINATEAXIS_H

coordinateaxis.cpp

#include "coordinateaxis.h"#include <Qt3DExtras/QCylinderMesh>
#include <Qt3DExtras/QConeMesh>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DCore/QTransform>void CoordinateAxis::createAxis(double length)
{m_axisLength = length;// 创建X轴(红色)createSingleAxis(length, QVector3D(1, 0, 0), QColor(255, 0, 0));// 创建Y轴(绿色)createSingleAxis(length, QVector3D(0, 1, 0), QColor(0, 255, 0));// 创建Z轴(蓝色)createSingleAxis(length, QVector3D(0, 0, 1), QColor(0, 0, 255));
}Qt3DCore::QEntity* CoordinateAxis::getAxisEntity() const
{return m_rootEntity;
}Qt3DCore::QEntity* CoordinateAxis::createSingleAxis(double length, const QVector3D& direction, const QColor& color)
{// 创建轴实体Qt3DCore::QEntity* axis = new Qt3DCore::QEntity(m_rootEntity);Qt3DCore::QEntity* axis1 = new Qt3DCore::QEntity(m_rootEntity);// 创建圆柱(轴主体)Qt3DExtras::QCylinderMesh* cylinderMesh = new Qt3DExtras::QCylinderMesh(axis);cylinderMesh->setRadius(axSz.cyR_);cylinderMesh->setLength(axSz.cyLen_);cylinderMesh->setSlices(20);    // 切片数cylinderMesh->setRings(200);    // 环数// 计算圆柱变换(位置和旋转)Qt3DCore::QTransform* cylinderTrans = new Qt3DCore::QTransform(axis);if (direction == QVector3D(1, 0, 0)) {// X轴:绕Z轴旋转90°,使圆柱体沿X轴正方向延伸cylinderTrans->setRotation(QQuaternion::fromEulerAngles(0, 0, -90));} else if (direction == QVector3D(0, 0, 1)) {// Z轴:绕X轴旋转90°,使圆柱体沿Z轴延伸cylinderTrans->setRotation(QQuaternion::fromEulerAngles(90, 0, 0));}// Y轴无需旋转(默认沿Y轴延伸)// 设置平移,使轴从原点开始到length长度cylinderTrans->setTranslation(direction * (float)(length / 2.0));// 创建材质Qt3DExtras::QPhongMaterial* material = new Qt3DExtras::QPhongMaterial(axis1);material->setDiffuse(color);// 创建圆锥(轴端点)Qt3DExtras::QConeMesh* coneMesh = new Qt3DExtras::QConeMesh(axis1);coneMesh->setBottomRadius(axSz.conR_);coneMesh->setLength(axSz.conLen_); // 锥体长coneMesh->setSlices(20);coneMesh->setRings(200);// 计算圆锥变换Qt3DCore::QTransform* coneTrans = new Qt3DCore::QTransform(axis1);coneTrans->setRotation(cylinderTrans->rotation()); // 与圆柱同方向// 圆锥位置:轴末端 + 圆锥长度的一半(使圆锥尖端朝外)// 关键修复:确保方向向量正确指向正方向coneTrans->setTranslation(direction * (float)length + direction * axSz.conLen_/2.0);// 添加组件到轴实体(关键修复:使用axis->addComponent)axis->addComponent(material);axis->addComponent(cylinderMesh);axis->addComponent(cylinderTrans);axis1->addComponent(coneMesh);axis1->addComponent(material);axis1->addComponent(coneTrans);return axis;
}// Qt3DCore::QEntity* CoordinateAxis::createSingleAxis(double length,const QVector3D& direction,const QColor& color)
// {
//     // 创建轴实体
//     Qt3DCore::QEntity* axis = new Qt3DCore::QEntity(m_rootEntity);//     // 创建圆柱(轴主体)
//     Qt3DExtras::QCylinderMesh* cylinderMesh = new Qt3DExtras::QCylinderMesh(axis);
//     cylinderMesh->setRadius(0.05f);
//     cylinderMesh->setLength(length);
//     cylinderMesh->setSlices(20);    //切片
//     cylinderMesh->setRings(200);    //环数//     // 计算圆柱变换(位置和旋转)
//     Qt3DCore::QTransform* cylinderTrans = new Qt3DCore::QTransform(m_rootEntity);//     if (direction == QVector3D(1, 0, 0)) {
//         // 修改前(错误):QQuaternion::fromEulerAngles(0, 180, 90)
//         // 修改后(正确):仅绕Z轴旋转90°,使圆柱体沿X轴延伸
//         cylinderTrans->setRotation(QQuaternion::fromEulerAngles(0, 0, 90));
//     } else if (direction == QVector3D(0, 0, 1)) {
//         // 保持正确:绕X轴旋转90°,使圆柱体沿Z轴延伸
//         cylinderTrans->setRotation(QQuaternion::fromEulerAngles(90, 0, 0));
//     }
//     // Y轴无需旋转(默认沿Y轴延伸),保持原逻辑//     // 设置平移,使轴从原点开始
//     cylinderTrans->setTranslation(direction * (float)(length / 2.0));//     // 创建材质
//     Qt3DExtras::QPhongMaterial* material = new Qt3DExtras::QPhongMaterial(m_rootEntity);
//     material->setDiffuse(color);//     // 创建圆锥(轴端点)
//     Qt3DExtras::QConeMesh* coneMesh = new Qt3DExtras::QConeMesh();
//     coneMesh->setBottomRadius(0.3f);
//     coneMesh->setLength(1.0f); // 锥体长
//     coneMesh->setSlices(20);    //切片
//     coneMesh->setRings(200);    //环数//     // 计算圆锥变换
//     Qt3DCore::QTransform* coneTrans = new Qt3DCore::QTransform();
//     coneTrans->setRotation(cylinderTrans->rotation()); // 与圆柱同方向
//     // 圆锥位置:轴末端 + 圆锥长度的一半(使圆锥尖端朝外)
//     coneTrans->setTranslation(direction * (float)(length) + direction * 0.5f);//     // 添加组件到轴实体
//     addComponent(material);
//     addComponent(cylinderMesh);
//     addComponent(cylinderTrans);
//     // axis->addComponent(coneMesh);
//     // axis->addComponent(material);
//     // axis->addComponent(coneTrans);//     return axis;
// }

实体管理类讲解:

实体管理类源码:

totalentity.h

#ifndef TOTALENTITY_H
#define TOTALENTITY_H#include <QWidget>
#include <QObject>
#include <QVector>
#include <QSize>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QCamera>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DExtras/Qt3DWindow>
#include <QScreen>
#include <Qt3DExtras/QForwardRenderer>class TotalEntity
{
public:TotalEntity();//创建场景void create3DScene();//创建摄像机void createCamera();//获取3D场景控件QWidget* get3DViewWidget();//获取对象实体类型template<class T>T* getEntityObject(){for (auto& entity : allEntity) {// 直接转换 “基类指针 entity(QEntity*)” 为 “派生类指针 T*(如 ArrowEntity*)”T* derivedEntity = dynamic_cast<T*>(entity);if (derivedEntity != nullptr) {return derivedEntity;}}return nullptr;}private://存储所有需要展示的对象实体QVector<Qt3DCore::QEntity*> allEntity;Qt3DCore::QEntity* m_rootEntity = nullptr;//祖宗跟实体Qt3DCore::QEntity* m_currentEntity = nullptr;//当前跟实体//窗口Qt3DExtras::Qt3DWindow *view = nullptr;               // 主3D视图Qt3DExtras::Qt3DWindow *previewView = nullptr;        // 预览3D视图//相机Qt3DRender::QCamera* camera = nullptr;Qt3DExtras::QOrbitCameraController *cameraController = nullptr; // 相机控制器//3D视图显示控件QWidget* Widget3D = nullptr;
};#endif // TOTALENTITY_H

totalentity.cpp

#include "totalentity.h"#include "arrowentity.h"
#include "coordinateaxis.h"TotalEntity::TotalEntity():m_rootEntity(new Qt3DCore::QEntity())
{create3DScene();createCamera();ArrowEntity* arrow = new ArrowEntity(m_rootEntity);// ArrowSize sz = {1,1,3,3};// arrow->setArrowLenAndRot(sz);CoordinateAxis* axis = new CoordinateAxis();axis->getAxisEntity()->setParent(arrow->getRootEntity());CoordinateAxis* axis1 = new CoordinateAxis();axis1->getAxisEntity()->setParent(m_rootEntity);// axis->setEnabled(false);// QVector3D pos(-2,-2,3);// arrow->setArrowPosition(pos);allEntity.append(arrow);allEntity.append(axis);
}void TotalEntity::create3DScene()
{if(view==nullptr){//创建3D视图view = new Qt3DExtras::Qt3DWindow();view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));//创建容纳3D视图的widgetWidget3D = QWidget::createWindowContainer(view);QSize screen = view->screen()->size();view->setMinimumSize(QSize(400,300));view->setMaximumSize(screen);//将跟实体设置到场景view->setRootEntity(m_rootEntity);}
}void TotalEntity::createCamera()
{if(view!=nullptr){//设置相机camera = view->camera();camera->lens()->setPerspectiveProjection(45.0f,16.0f/9.0f,1.0f,1000.0f);camera->setPosition(QVector3D(0,0,20));camera->setViewCenter(QVector3D(3,3,3));// 相机控制器 - 支持鼠标拖拽旋转、滚轮缩放cameraController = new Qt3DExtras::QOrbitCameraController(m_rootEntity);cameraController->setCamera(camera);cameraController->setLinearSpeed(50.0f);  // 平移速度cameraController->setLookSpeed(180.0f);   // 旋转速度//创建光源// Qt3DRender::QPointLight* light = new Qt3DRender::QPointLight();Qt3DRender::QDirectionalLight* light = new Qt3DRender::QDirectionalLight();// light->setIntensity(1.0f);// light->setColor("white");light->setColor(QColor(Qt::white));light->setIntensity(1.0f);light->setWorldDirection(QVector3D(-5, 1, 1));Qt3DCore::QTransform* lightTrans = new Qt3DCore::QTransform();lightTrans->setTranslation(QVector3D(10,10,20));//光源位置//光实体Qt3DCore::QEntity* lightEntity = new Qt3DCore::QEntity();lightEntity->addComponent(light);lightEntity->addComponent(lightTrans);lightEntity->setParent(camera);}else{qDebug()<<"view is nullptr,cannot create camera.";}
}QWidget* TotalEntity::get3DViewWidget()
{return Widget3D?Widget3D:nullptr; //感觉多次一举 在调用的地方判断不就可以了
}

界面控件设置类:

界面控件设置类源码:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QWidget>
#include <QString>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QLayout>
#include <QPushButton>
#include <QCheckBox>
#include <QSlider>
#include <QLabel>
#include <QTimer>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QLineEdit>#include "totalentity.h"
#include "arrowentity.h"
class ArrowEntity;class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();//创建控制面板void createControlWidget();//对所有控件进行信号和槽的绑定void allSignalBindSlot();public slots://重置视图void onResetView();//是否自动旋转void onToggleAutoRotation(bool checked);//输入框void on_XSpinBox(int x);void on_YSpinBox(int y);void on_ZSpinBox(int z);void on_speedSpinBox(int speed);void on_XLineEdit(const QString& x);void on_YLineEdit(const QString& y);void on_ZLineEdit(const QString& z);void on_SpeedLineEdit(const QString& speed);//实体信息槽函数void on_xEdit(const QString& x);void on_yEdit(const QString& y);void on_zEdit(const QString& z);void on_cyEdit(const QString& cyLen);void on_cyREdit(const QString& cyR);void on_conEdit(const QString& conLen);void on_conREdit(const QString& conR);void onCylinderColorSelected();void onConeColorSelected();void onSetEntityVisible(int flag);private://需要嵌入到 view的QWidget控件QWidget* widget3DView = nullptr;TotalEntity* rootEntity = nullptr;//滑杆控件QSlider *xRotSlider = nullptr;QSlider *yRotSlider = nullptr;QSlider *zRotSlider = nullptr;QSlider *speedSlider = nullptr;//输入框QLineEdit* xSpinBox = nullptr;QLineEdit* ySpinBox = nullptr;QLineEdit* zSpinBox = nullptr;QLineEdit* speedSpinBox = nullptr;//属性半径 信息QLineEdit* xEdit = nullptr;QLineEdit* yEdit = nullptr;QLineEdit* zEdit = nullptr;QLineEdit* cyEdit = nullptr;QLineEdit* cyREdit = nullptr;QLineEdit* conEdit = nullptr;QLineEdit* conREdit = nullptr;QLineEdit* xArrDirEdit = nullptr;QLineEdit* yArrDirEdit = nullptr;QLineEdit* zArrDirEdit = nullptr;QVector3D entityPos;ArrowSize att;//单选框// QCheckBox *autoRotateCheckBox = nullptr;//有点多余QCheckBox *coordModeCheckBox = nullptr;//颜色选择按钮QPushButton *cylinderColorBtn = nullptr;QPushButton *coneColorBtn = nullptr;QPushButton *resetBtn = nullptr;//定时器QTimer* autoRotateTimer = nullptr;
};
#endif // MAINWINDOW_H

mainwindow..cpp

#include "mainwindow.h"#include "arrowentity.h"
#include "coordinateaxis.h"
class ArrowEntity;MainWindow::MainWindow(QWidget *parent): QMainWindow(parent),rootEntity(new TotalEntity())
{widget3DView = rootEntity->get3DViewWidget();createControlWidget();allSignalBindSlot();
}MainWindow::~MainWindow() {}void MainWindow::createControlWidget()
{// 创建控制面板QWidget *controlPanel = new QWidget();QVBoxLayout *controlLayout = new QVBoxLayout(controlPanel);// 添加标题QLabel *titleLabel = new QLabel("<h3>模型控制器</h3>");controlLayout->addWidget(titleLabel);// 旋转控制 - X轴QHBoxLayout *xRotLayout = new QHBoxLayout();xRotLayout->addWidget(new QLabel("X轴旋转:"));xRotSlider = new QSlider(Qt::Horizontal);xRotSlider->setRange(0, 360);xRotSlider->setValue(0);xRotLayout->addWidget(xRotSlider);// xSpinBox = new QDoubleSpinBox();// xSpinBox->setMaximum(360);// xSpinBox->setMinimum(0);xSpinBox = new QLineEdit();// 创建整数验证器,设置范围0-360QIntValidator *xvalidator = new QIntValidator(0, 360, xSpinBox);// 设置验证器到QLineEditxSpinBox->setValidator(xvalidator);// 可选:设置输入提示xSpinBox->setPlaceholderText("0-360整数");xRotLayout->addWidget(xSpinBox);controlLayout->addLayout(xRotLayout);// 旋转控制 - Y轴QHBoxLayout *yRotLayout = new QHBoxLayout();yRotLayout->addWidget(new QLabel("Y轴旋转:"));yRotSlider = new QSlider(Qt::Horizontal);yRotSlider->setRange(0, 360);yRotSlider->setValue(0);yRotLayout->addWidget(yRotSlider);ySpinBox = new QLineEdit();// 创建整数验证器,设置范围0-360QIntValidator *yvalidator = new QIntValidator(0, 360, ySpinBox);// 设置验证器到QLineEditySpinBox->setValidator(yvalidator);// 可选:设置输入提示ySpinBox->setPlaceholderText("0-360整数");yRotLayout->addWidget(ySpinBox);controlLayout->addLayout(yRotLayout);// 旋转控制 - Z轴QHBoxLayout *zRotLayout = new QHBoxLayout();zRotLayout->addWidget(new QLabel("Z轴旋转:"));zRotSlider = new QSlider(Qt::Horizontal);zRotSlider->setRange(0, 360);zRotSlider->setValue(0);zRotLayout->addWidget(zRotSlider);zSpinBox = new QLineEdit();// 创建整数验证器,设置范围0-360QIntValidator *zvalidator = new QIntValidator(0, 360, zSpinBox);// 设置验证器到QLineEditzSpinBox->setValidator(zvalidator);// 可选:设置输入提示zSpinBox->setPlaceholderText("0-360整数");zRotLayout->addWidget(zSpinBox);controlLayout->addLayout(zRotLayout);// // 旋转速度控制// QHBoxLayout *speedLayout = new QHBoxLayout();// speedLayout->addWidget(new QLabel("旋转速度:"));// speedSlider = new QSlider(Qt::Horizontal);// speedSlider->setRange(1, 10);// speedSlider->setValue(2);// speedLayout->addWidget(speedSlider);// speedSpinBox = new QLineEdit();// 创建整数验证器,设置范围0-360// QIntValidator *speedvalidator = new QIntValidator(0, 360, speedSpinBox);// // 设置验证器到QLineEdit// speedSpinBox->setValidator(speedvalidator);// // 可选:设置输入提示// speedSpinBox->setPlaceholderText("1-10整数");// speedLayout->addWidget(speedSpinBox);// controlLayout->addLayout(speedLayout);//设置实体的空间坐标系QWidget* posWidget = new QWidget(this);QGridLayout* posLayout = new QGridLayout(posWidget);QLabel* xlabel = new QLabel("X坐标:",this);xEdit = new QLineEdit(this);xEdit->setPlaceholderText("请输入数值");QLabel* ylabel = new QLabel("Y坐标:",this);yEdit = new QLineEdit(this);yEdit->setPlaceholderText("请输入数值");QLabel* zlabel = new QLabel("Z坐标:",this);zEdit = new QLineEdit(this);zEdit->setPlaceholderText("请输入数值");posLayout->addWidget(xlabel,0,0);posLayout->addWidget(xEdit,0,1);posLayout->addWidget(ylabel,1,0);posLayout->addWidget(yEdit,1,1);posLayout->addWidget(zlabel,2,0);posLayout->addWidget(zEdit,2,1);controlLayout->addWidget(posWidget);//设置圆柱 圆锥 长 半径QWidget* entityAttribute = new QWidget(this);QGridLayout* attLayout = new QGridLayout(entityAttribute);QLabel* cylabel = new QLabel("圆柱长度:",this);cyEdit = new QLineEdit(this);cyEdit->setPlaceholderText("请输入长度");QLabel* cyRlabel = new QLabel("圆柱半径:",this);cyREdit = new QLineEdit(this);cyREdit->setPlaceholderText("请输入半径");QLabel* conlabel = new QLabel("圆锥长度:",this);conEdit = new QLineEdit(this);conEdit->setPlaceholderText("请输入长度");QLabel* conRlabel = new QLabel("圆锥半径:",this);conREdit = new QLineEdit(this);conREdit->setPlaceholderText("请输入半径");attLayout->addWidget(cylabel,0,0);attLayout->addWidget(cyEdit,0,1);attLayout->addWidget(cyRlabel,0,2);attLayout->addWidget(cyREdit,0,3);attLayout->addWidget(conlabel,1,0);attLayout->addWidget(conEdit,1,1);attLayout->addWidget(conRlabel,1,2);attLayout->addWidget(conREdit,1,3);controlLayout->addWidget(entityAttribute);//设置箭头的朝向QWidget* arrowDirect = new QWidget(this);QGridLayout* arrowDirectLayout = new QGridLayout(arrowDirect);QLabel* xArrDirlabel = new QLabel("箭头X轴方向:",this);xArrDirEdit = new QLineEdit(this);xArrDirEdit->setPlaceholderText("请输入X长度");QLabel* yArrDirlabel = new QLabel("箭头Y轴方向:",this);yArrDirEdit = new QLineEdit(this);yArrDirEdit->setPlaceholderText("请输入Y长度");QLabel* zArrDirlabel = new QLabel("箭头Z轴方向:",this);zArrDirEdit = new QLineEdit(this);zArrDirEdit->setPlaceholderText("请输入Z长度");arrowDirectLayout->addWidget(xArrDirlabel,0,0);arrowDirectLayout->addWidget(xArrDirEdit,0,1);arrowDirectLayout->addWidget(yArrDirlabel,1,0);arrowDirectLayout->addWidget(yArrDirEdit,1,1);arrowDirectLayout->addWidget(zArrDirlabel,2,0);arrowDirectLayout->addWidget(zArrDirEdit,2,1);controlLayout->addWidget(arrowDirect);// // 自动旋转复选框// autoRotateCheckBox = new QCheckBox("自动旋转");// controlLayout->addWidget(autoRotateCheckBox);// 坐标系模式切换coordModeCheckBox = new QCheckBox("只显示坐标系");controlLayout->addWidget(coordModeCheckBox);// 颜色选择按钮 - 圆柱体cylinderColorBtn = new QPushButton("选择圆柱体颜色");controlLayout->addWidget(cylinderColorBtn);// 颜色选择按钮 - 圆锥体coneColorBtn = new QPushButton("选择圆锥体颜色");controlLayout->addWidget(coneColorBtn);// 重置按钮resetBtn = new QPushButton("重置视图");controlLayout->addWidget(resetBtn);// 添加伸缩项,使控件靠上显示controlLayout->addStretch();// 主布局 - 包含预览窗口QWidget *mainContainer = new QWidget();QVBoxLayout *mainContainerLayout = new QVBoxLayout(mainContainer);// // 预览窗口容器// QWidget *previewContainer = QWidget::createWindowContainer(previewView);// previewContainer->setFixedSize(200, 200); // 预览窗口大小//顶部布局 - 主视图和预览窗口QHBoxLayout *topLayout = new QHBoxLayout();topLayout->addWidget(widget3DView, 1);// // 预览窗口放在右上角// QVBoxLayout *previewLayout = new QVBoxLayout();// previewLayout->addStretch();// previewLayout->addWidget(previewContainer, 0, Qt::AlignRight);// topLayout->addLayout(previewLayout);mainContainerLayout->addLayout(topLayout);// 主布局QHBoxLayout *mainLayout = new QHBoxLayout();mainLayout->addWidget(controlPanel, 3);  // 控制面板占30%宽度mainLayout->addWidget(mainContainer, 7); // 3D视图占70%宽度// 主窗口设置QWidget *mainWidget = new QWidget();mainWidget->setLayout(mainLayout);setCentralWidget(mainWidget);setWindowTitle("Qt3D 坐标系演示");resize(1200, 800);
}void MainWindow::allSignalBindSlot()
{//创建定时器autoRotateTimer = new QTimer();ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow!=nullptr){// 连接信号槽connect(xRotSlider, &QSlider::valueChanged, arrow, &ArrowEntity::onXRotationChanged);connect(yRotSlider, &QSlider::valueChanged, arrow, &ArrowEntity::onYRotationChanged);connect(zRotSlider, &QSlider::valueChanged, arrow, &ArrowEntity::onZRotationChanged);// connect(speedSlider, &QSlider::valueChanged, arrow, &ArrowEntity::onRotationSpeedChanged);connect(cylinderColorBtn, &QPushButton::clicked, this, &MainWindow::onCylinderColorSelected);connect(coneColorBtn, &QPushButton::clicked, this, &MainWindow::onConeColorSelected);connect(xArrDirEdit, &QLineEdit::textEdited, arrow, &ArrowEntity::onXDirect);connect(yArrDirEdit, &QLineEdit::textEdited, arrow, &ArrowEntity::onYDirect);connect(zArrDirEdit, &QLineEdit::textEdited, arrow, &ArrowEntity::onZDirect);connect(coordModeCheckBox, &QCheckBox::stateChanged, this, &MainWindow::onSetEntityVisible);}// connect(autoRotateCheckBox, &QCheckBox::toggled, this, &MainWindow::onToggleAutoRotation);connect(resetBtn, &QPushButton::clicked, this, &MainWindow::onResetView);//实体坐标 圆柱 圆锥半径 长度connect(xEdit,&QLineEdit::textEdited,this,&MainWindow::on_xEdit);connect(zEdit,&QLineEdit::textEdited,this,&MainWindow::on_yEdit);connect(yEdit,&QLineEdit::textEdited,this,&MainWindow::on_zEdit);connect(cyEdit,&QLineEdit::textEdited,this,&MainWindow::on_cyEdit);connect(cyREdit,&QLineEdit::textEdited,this,&MainWindow::on_cyREdit);connect(conEdit,&QLineEdit::textEdited,this,&MainWindow::on_conEdit);connect(conREdit,&QLineEdit::textEdited,this,&MainWindow::on_conREdit);//输入框connect(xSpinBox,&QLineEdit::textEdited,this,&MainWindow::on_XLineEdit);connect(ySpinBox,&QLineEdit::textEdited,this,&MainWindow::on_YLineEdit);connect(zSpinBox,&QLineEdit::textEdited,this,&MainWindow::on_ZLineEdit);// connect(speedSpinBox,&QLineEdit::textEdited,this,&MainWindow::on_SpeedLineEdit);connect(xRotSlider, &QSlider::valueChanged, this,&MainWindow::on_XSpinBox);connect(yRotSlider, &QSlider::valueChanged, this,&MainWindow::on_YSpinBox);connect(zRotSlider, &QSlider::valueChanged, this,&MainWindow::on_ZSpinBox);// connect(speedSlider, &QSlider::valueChanged, this,&MainWindow::on_speedSpinBox);
}void MainWindow::onResetView()
{// 重置滑块QList<QSlider*> sliders = findChildren<QSlider*>();for (int i = 0; i < sliders.size() && i < 3; ++i) {sliders[i]->setValue(0);}// 停止自动旋转autoRotateTimer->stop();QCheckBox* autoRotateCheckBox = findChild<QCheckBox*>();if (autoRotateCheckBox) {autoRotateCheckBox->setChecked(false);}ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow==nullptr){qDebug()<<"MainWindow::allSignalBindSlot:get class Failed.";return ;}arrow->ResetView();
}void MainWindow::onToggleAutoRotation(bool checked)
{if (checked) {autoRotateTimer->start(50); // 每50毫秒更新一次} else {autoRotateTimer->stop();}
}void MainWindow::on_XSpinBox(int x)
{if(sender()==xRotSlider)xSpinBox->setText(QString::number(x, 10));else if(sender()==xSpinBox)xRotSlider->setValue(x);
}void MainWindow::on_YSpinBox(int y)
{if(sender()==yRotSlider)ySpinBox->setText(QString::number(y, 10));else if(sender()==ySpinBox)yRotSlider->setValue(y);
}void MainWindow::on_ZSpinBox(int z)
{if(sender()==zRotSlider)zSpinBox->setText(QString::number(z, 10));else if(sender()==zSpinBox)zRotSlider->setValue(z);
}void MainWindow::on_speedSpinBox(int speed)
{if(sender()==speedSlider)speedSpinBox->setText(QString::number(speed, 10));else if(sender()==speedSpinBox)speedSlider->setValue(speed);
}void MainWindow::on_XLineEdit(const QString &x)
{xRotSlider->setValue(x.toInt());
}void MainWindow::on_YLineEdit(const QString &y)
{yRotSlider->setValue(y.toInt());
}void MainWindow::on_ZLineEdit(const QString &z)
{zRotSlider->setValue(z.toInt());
}void MainWindow::on_SpeedLineEdit(const QString &speed)
{speedSlider->setValue(speed.toInt());
}void MainWindow::on_xEdit(const QString &x)
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow==nullptr){qDebug()<<"MainWindow::allSignalBindSlot:get class Failed.";return ;}entityPos.setX(x.toDouble());arrow->setArrowPosition(entityPos);
}void MainWindow::on_yEdit(const QString &y)
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow==nullptr){qDebug()<<"MainWindow::allSignalBindSlot:get class Failed.";return ;}entityPos.setY(y.toDouble());arrow->setArrowPosition(entityPos);
}void MainWindow::on_zEdit(const QString &z)
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow==nullptr){qDebug()<<"MainWindow::allSignalBindSlot:get class Failed.";return ;}entityPos.setZ(z.toDouble());arrow->setArrowPosition(entityPos);
}void MainWindow::on_cyEdit(const QString &cyLen)
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow==nullptr){qDebug()<<"MainWindow::allSignalBindSlot:get class Failed.";// return ;}att.cyLen_ = cyLen.toDouble();arrow->setArrowLenAndRot(att);
}void MainWindow::on_cyREdit(const QString &cyR)
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow==nullptr){qDebug()<<"MainWindow::allSignalBindSlot:get class Failed.";return ;}att.cyR_ = cyR.toDouble();arrow->setArrowLenAndRot(att);
}void MainWindow::on_conEdit(const QString &conLen)
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow==nullptr){qDebug()<<"MainWindow::allSignalBindSlot:get class Failed.";return ;}att.conLen_ = conLen.toDouble();arrow->setArrowLenAndRot(att);
}void MainWindow::on_conREdit(const QString &conR)
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow==nullptr){qDebug()<<"MainWindow::allSignalBindSlot:get class Failed.";return ;}att.conR_ = conR.toDouble();arrow->setArrowLenAndRot(att);
}void MainWindow::onCylinderColorSelected()
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow!=nullptr){QColor color = QColorDialog::getColor(arrow->getCyColor(), this, "选择圆柱体颜色");if (color.isValid()) {arrow->setCylinderColorSelected(color);}}
}void MainWindow::onConeColorSelected()
{ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow!=nullptr){QColor color = QColorDialog::getColor(arrow->getCyColor(), this, "选择圆锥体颜色");if (color.isValid()) {arrow->setConeColorSelected(color);}}
}void MainWindow::onSetEntityVisible(int flag)
{if(Qt::Unchecked == flag){ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow!=nullptr){arrow->setEnabled(true);}}else if(Qt::Checked == flag){ArrowEntity* arrow = rootEntity->getEntityObject<ArrowEntity>();if(arrow!=nullptr){arrow->setEnabled(false);}}
}

工程MakeList.txt

cmake_minimum_required(VERSION 3.19)
project(3DModelArrow LANGUAGES CXX)find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets3DCore3DRender3DExtras3DInput)qt_standard_project_setup()qt_add_executable(3DModelArrowWIN32 MACOSX_BUNDLEmain.cppmainwindow.cppmainwindow.harrowentity.h arrowentity.cppcoordinateaxis.h coordinateaxis.cpptotalentity.h totalentity.cpp
)target_link_libraries(3DModelArrowPRIVATEQt::CoreQt::WidgetsQt6::3DCoreQt6::3DRenderQt6::3DExtrasQt6::3DInput
)include(GNUInstallDirs)install(TARGETS 3DModelArrowBUNDLE  DESTINATION .RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)qt_generate_deploy_app_script(TARGET 3DModelArrowOUTPUT_SCRIPT deploy_scriptNO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

http://www.dtcms.com/a/445646.html

相关文章:

  • 自助建子站龙口网络
  • 【QT常用技术讲解】opencv实现指定分辨率打开摄像头
  • ICT 数字测试原理 7 - -VCL 测试环境
  • stp mode mstp 概念及题目
  • ASP4644芯片低功耗设计思路解析
  • Qt 开发修炼指南:从入门到通透的实战心法
  • 怎么格式化idea中的vue文件
  • MATLAB计算标准化加权平均降水量(Weighted Average Precipitation,SWAP)
  • Leetcode 3702. Longest Subsequence With Non-Zero Bitwise XOR
  • 通辽网站公司福州微信网站建设
  • 网页制作的网站建设wordpress 闪图不
  • 访客申请表添加业主信息字段 - 部署说明
  • Faster RCNN - RPN作用原理
  • 响应式公司网站高端大气公司名称
  • C++之模板进阶:非类型参typename的作用,特化设计与分离编译
  • 树莓派上市后的开源抉择:价格、纯度与生态
  • 顺丰科技java面经准备
  • 数据库的ALTER权限失效
  • 业绩连降两年,大幅减员缩降成本,极米科技赴港IPO挑战仍不少
  • 南昌做网站价格安康市网约车平台
  • 【Linux】Shell编程(二):grep - 文本搜索利器
  • Redis为啥是单线程的
  • 做网站挣钱的人东莞网站建设方案维护
  • g3云网站地方新闻门户网站源码
  • SD:在一个 Ubuntu 系统安装 stable diffusion Web UI
  • WebSocket网络编程(TCP/UDP)
  • 经典架构解读
  • 今天,是你成为创作者的第1024天
  • [linux仓库]图解System V共享内存:从shmget到内存映射的完整指南
  • 大模型-扩散模型(Diffusion Model)原理讲解(3)