赞
踩
官方网站:https://www.roboticslibrary.org/
参考指南:https://www.roboticslibrary.org/tutorials/
// // Copyright (c) 2009, Markus Rickert // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // #include <QDoubleSpinBox> #include <QModelIndex> #include "ConfigurationDelegate.h" #include "MainWindow.h" ConfigurationDelegate::ConfigurationDelegate(QObject* parent) : QItemDelegate(parent) { } ConfigurationDelegate::~ConfigurationDelegate() { } QWidget* ConfigurationDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { QDoubleSpinBox* editor = new QDoubleSpinBox(parent); rl::math::Vector maximum = MainWindow::instance()->model->getMaximum(); rl::math::Vector minimum = MainWindow::instance()->model->getMinimum(); Eigen::Matrix<rl::math::Unit, Eigen::Dynamic, 1> qUnits = MainWindow::instance()->model->getPositionUnits(); if (rl::math::UNIT_RADIAN == qUnits(index.row())) { editor->setDecimals(2); editor->setMinimum(minimum(index.row()) * rl::math::RAD2DEG); editor->setMaximum(maximum(index.row()) * rl::math::RAD2DEG); editor->setSingleStep(1.0f); } else { editor->setDecimals(4); editor->setMinimum(minimum(index.row())); editor->setMaximum(maximum(index.row())); editor->setSingleStep(0.01f); } QObject::connect(editor, SIGNAL(valueChanged(double)), this, SLOT(valueChanged(double))); return editor; } void ConfigurationDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { QDoubleSpinBox* doubleSpinBox = static_cast<QDoubleSpinBox*>(editor); doubleSpinBox->setValue(index.model()->data(index, Qt::EditRole).toDouble()); } void ConfigurationDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { QDoubleSpinBox* doubleSpinBox = static_cast<QDoubleSpinBox*>(editor); doubleSpinBox->interpretText(); model->setData(index, doubleSpinBox->value(), Qt::EditRole); } void ConfigurationDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { editor->setGeometry(option.rect); } void ConfigurationDelegate::valueChanged(double d) { emit commitData(static_cast<QWidget*>(QObject::sender())); }
include<> : 编译器直接从系统类库目录里查找头文件
include “” : 默认从项目当前目录查找头文件,所谓项目当前目录,就是项目工程文件(*.vcxproj) 所在的目录
取反的意思——析构函数
析构函数与构造函数相反:
当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
C++语言:析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数,它也不进行任何操作。所以许多简单的类中没有用显示的析构函数。
QObject *parent/QWidget *parent,当指定了parent后,Qt就会介入,在合适的时候调用对应的delete操作
Qt析构机制参考
Qt使用model/view 模式,一般来讲, model是数据,view把数据展示给用户,数据与界面的交互则通过delegagte来执行。
QItemDelegate类为模型中的数据项提供了显示和编辑的工具,从中派生创建自定义委托代理类。
机器人库:
主要机器人领域的所有重要算法,包括运动学、动力学、轨迹生成和路径规划,都是可用的,并使用相同的符号和接口。
rl::math::Vector 正向运动学
// // Copyright (c) 2009, Markus Rickert // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // #include "ConfigurationModel.h" #include "MainWindow.h" #include "Thread.h" #include "Viewer.h" ConfigurationModel::ConfigurationModel(QObject* parent) : QAbstractTableModel(parent) { } ConfigurationModel::~ConfigurationModel() { } int ConfigurationModel::columnCount(const QModelIndex& parent) const { return 1; } QVariant ConfigurationModel::data(const QModelIndex& index, int role) const { if (nullptr == MainWindow::instance()->model) { return QVariant(); } if (!index.isValid()) { return QVariant(); } switch (role) { case Qt::DisplayRole: case Qt::EditRole: { Eigen::Matrix<rl::math::Unit, Eigen::Dynamic, 1> qUnits = MainWindow::instance()->model->getPositionUnits(); if (rl::math::UNIT_RADIAN == qUnits(index.row())) { return (*MainWindow::instance()->q)(index.row()) * rl::math::RAD2DEG; } else { return (*MainWindow::instance()->q)(index.row()); } } case Qt::TextAlignmentRole: return QVariant(Qt::AlignRight | Qt::AlignVCenter); break; default: break; } return QVariant(); } Qt::ItemFlags ConfigurationModel::flags(const QModelIndex &index) const { if (!index.isValid()) { return Qt::NoItemFlags; } return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; } QVariant ConfigurationModel::headerData(int section, Qt::Orientation orientation, int role) const { if (Qt::DisplayRole == role && Qt::Vertical == orientation) { return QString::number(section); } return QVariant(); } void ConfigurationModel::invalidate() { this->beginResetModel(); this->endResetModel(); } int ConfigurationModel::rowCount(const QModelIndex& parent) const { if (nullptr == MainWindow::instance()->model) { return 0; } return MainWindow::instance()->model->getDofPosition(); } bool ConfigurationModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (nullptr == MainWindow::instance()->model) { return false; } if (MainWindow::instance()->thread->isRunning()) { return false; } if (index.isValid() && Qt::EditRole == role) { Eigen::Matrix<rl::math::Unit, Eigen::Dynamic, 1> qUnits = MainWindow::instance()->model->getPositionUnits(); if (rl::math::UNIT_RADIAN == qUnits(index.row())) { (*MainWindow::instance()->q)(index.row()) = value.value<rl::math::Real>() * rl::math::DEG2RAD; } else { (*MainWindow::instance()->q)(index.row()) = value.value<rl::math::Real>(); } MainWindow::instance()->viewer->drawConfiguration(*MainWindow::instance()->q); emit dataChanged(index, index); return true; } return false; }
Model/View结构原理参考1
Model/View结构原理参考2
实际数据Data与界面组件View之间通过Model通信,Model为视图组件提供数据接口——从原始数据Data中提取需要的部分在视图组件中显示和编辑。
Delegate委托代理功能使得用户可以编辑内容和定制界面。
Model类:定义了模型访问接口。负责访问数据集中的数据项;
Delegate类:负责视图中每个数据项的绘制与编辑;
View类:负责绘制总体外观并处理用户的交互命令。
QAbstractTableModel接口需要被继承后实现相关的函数后使用,将数据用二维表格显示:
指针空值
- int columnCount 表格列数
- int rowCount 表格行数
- QVariant data 根据模型索引当前数据 【最主要的】
获取列数:直接返回1。
注:固定的数据列表,而非动态加载的,需要调用 insertRows()、removeRows()、insertColumns() 和 removeColumns() 实现视图大小的调整。
获取单元格数据。
两个参数:
1.QModelIndex 模型索引 :模型检索或修改数据,唯一确定一个数据项
2. role 角色
此处包含
用switch变换角色,然后返回任意类型的数据。
此处flag()函数只需要表达可编辑:单元格支持编辑操作,返回编辑后的数据。
获取表头信息:
此处返回列表头信息。
刷新view:修改view的显示后调用invalidate()函数才能重新看到绘制的界面。
必须在UI线程中工作。
此处返回实际的行数。
可编辑的模型必须重写setData()函数。
dataChanged()信号
向量空间模型
// // Copyright (c) 2009, Markus Rickert // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // #include "ConfigurationSpaceModel.h" #include "ConfigurationSpaceScene.h" #include "MainWindow.h" #include "Thread.h" #include "Viewer.h" ConfigurationSpaceModel::ConfigurationSpaceModel(QObject* parent) : QAbstractTableModel(parent), configurationSpaceScene(nullptr) { } ConfigurationSpaceModel::~ConfigurationSpaceModel() { } int ConfigurationSpaceModel::columnCount(const QModelIndex& parent) const { return 1; } QVariant ConfigurationSpaceModel::data(const QModelIndex& index, int role) const { if (nullptr == this->configurationSpaceScene) { return QVariant(); } if (nullptr == this->configurationSpaceScene->model) { return QVariant(); } if (!index.isValid()) { return QVariant(); } switch (role) { case Qt::DisplayRole: case Qt::EditRole: switch (index.row()) { case 0: return static_cast<unsigned int>(this->configurationSpaceScene->axis0); break; case 1: return static_cast<unsigned int>(this->configurationSpaceScene->axis1); break; case 2: return this->configurationSpaceScene->delta0; break; case 3: return this->configurationSpaceScene->delta1; break; default: break; } break; case Qt::TextAlignmentRole: return QVariant(Qt::AlignRight | Qt::AlignVCenter); break; default: break; } return QVariant(); } Qt::ItemFlags ConfigurationSpaceModel::flags(const QModelIndex &index) const { if (!index.isValid()) { return Qt::NoItemFlags; } return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; } QVariant ConfigurationSpaceModel::headerData(int section, Qt::Orientation orientation, int role) const { if (nullptr == this->configurationSpaceScene) { return QVariant(); } if (nullptr == this->configurationSpaceScene->model) { return QVariant(); } if (Qt::DisplayRole == role && Qt::Vertical == orientation) { switch (section) { case 0: return "axis0"; break; case 1: return "axis1"; break; case 2: return "delta0"; break; case 3: return "delta1"; break; default: break; } } return QVariant(); } void ConfigurationSpaceModel::invalidate() { this->beginResetModel(); this->endResetModel(); } int ConfigurationSpaceModel::rowCount(const QModelIndex& parent) const { if (nullptr == this->configurationSpaceScene) { return 0; } if (nullptr == this->configurationSpaceScene->model) { return 0; } return 4; } bool ConfigurationSpaceModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (nullptr == this->configurationSpaceScene) { return false; } if (nullptr == this->configurationSpaceScene->model) { return false; } if (MainWindow::instance()->thread->isRunning()) { return false; } if (index.isValid() && Qt::EditRole == role) { switch (index.row()) { case 0: if (value.value<std::size_t>() < this->configurationSpaceScene->model->getDofPosition()) { this->configurationSpaceScene->axis0 = value.value<std::size_t>(); } else { return false; } break; case 1: if (value.value<std::size_t>() < this->configurationSpaceScene->model->getDofPosition()) { this->configurationSpaceScene->axis1 = value.value<std::size_t>(); } else { return false; } break; case 2: if (value.value<rl::math::Real>() > 0) { this->configurationSpaceScene->delta0 = value.value<rl::math::Real>(); } else { return false; } break; case 3: if (value.value<rl::math::Real>() > 0) { this->configurationSpaceScene->delta1 = value.value<rl::math::Real>(); } else { return false; } break; default: break; } this->configurationSpaceScene->init(); emit dataChanged(index, index); return true; } return false; }
static_cast为强制类型转换,具体形式为:
staic_cast<new_type>(expresstion)
注:static_cast不能将const类型进行转化(const_cast可以)
方向:
axis=0时,表示纵轴,方向从上到下;
axis=1时,表示横轴,方向从左到右。
δ函数也可以理解为(任意阶可微)函数序列的极限。
返回1列
可编辑数据时,根据这4行表头信息进行检索
单元格可编辑
section标识第几行或者第几列,此处自定义表头:
在四行的表头分别返回"axis0"、“axis1”、“delta0”、“delta1”
刷新view,线程中进行
4行
根据实际的真实输入数据确定
#ifndef CONFIGURATIONDELEGATE_H #define CONFIGURATIONDELEGATE_H #include <QItemDelegate> class ConfigurationDelegate : public QItemDelegate { Q_OBJECT public: ConfigurationDelegate(QObject* parent = nullptr); virtual ~ConfigurationDelegate(); QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; void setEditorData(QWidget* editor, const QModelIndex& index) const; void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const; public slots: void valueChanged(double d); protected: private: }; #endif // CONFIGURATIONDELEGATE_H
#ifndef XX_H
#define XX_H
…
#endif
宏定义的作用
多个文件都包含同一个头文件时,容易造成编译混乱,加上ifndef/define/endif,就可以防止这种重定义错误。
虚析构函数有无的输出区别
类的析构函数:释放内存资源
virtual的析构函数:实现多态,释放子类空间
当一个类被用作基类,把析构函数写成虚函数。
自定义委托函数同上。
#ifndef CONFIGURATIONMODEL_H #define CONFIGURATIONMODEL_H #include <QAbstractTableModel> class ConfigurationModel : public QAbstractTableModel { public: ConfigurationModel(QObject* parent = nullptr); virtual ~ConfigurationModel(); int columnCount(const QModelIndex& parent = QModelIndex()) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; void invalidate(); int rowCount(const QModelIndex& parent = QModelIndex()) const; bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); protected: private: }; #endif // CONFIGURATIONMODEL_H
定义函数类型,函数含义见上一篇,ConfigurationSpaceModel.h同
从此处开始,先阅读.h文件,再贯穿.cpp文件,顺序改变
#ifndef CONFIGURATIONSPACESCENE_H #define CONFIGURATIONSPACESCENE_H #include <QGraphicsLineItem> #include <QGraphicsScene> #include <QLinkedList> #include <rl/plan/Model.h> #include <rl/plan/Viewer.h> class ConfigurationSpaceThread; class ConfigurationSpaceScene : public QGraphicsScene, public rl::plan::Viewer { Q_OBJECT public: ConfigurationSpaceScene(QObject* parent = nullptr); virtual ~ConfigurationSpaceScene(); std::size_t axis0; std::size_t axis1; rl::math::Real delta0; rl::math::Real delta1; rl::plan::Model* model; public slots: void addCollision(const qreal& x, const qreal& y, const qreal& w, const qreal& h, const int& rgb); void clear(); void drawConfiguration(const rl::math::Vector& q); void drawConfigurationEdge(const rl::math::Vector& u, const rl::math::Vector& v, const bool& free = true); void drawConfigurationPath(const rl::plan::VectorList& path); void drawConfigurationVertex(const rl::math::Vector& q, const bool& free = true); void drawLine(const rl::math::Vector& xyz0, const rl::math::Vector& xyz1); void drawPoint(const rl::math::Vector& xyz); void drawSphere(const rl::math::Vector& center, const rl::math::Real& radius); void drawSweptVolume(const rl::plan::VectorList& path); void drawWork(const rl::math::Transform& t); void drawWorkEdge(const rl::math::Vector& u, const rl::math::Vector& v); void drawWorkPath(const rl::plan::VectorList& path); void drawWorkVertex(const rl::math::Vector& q); void eval(); void init(); void reset(); void resetEdges(); void resetLines(); void resetPath(); void resetPoints(); void resetSpheres(); void resetVertices(); void showMessage(const std::string& message); protected: void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent); void mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent); private: QLinkedList<QGraphicsLineItem*> edges; QLinkedList<QGraphicsLineItem*> path; QGraphicsRectItem* scene; ConfigurationSpaceThread* thread; signals: void evalFinished(); }; #endif // CONFIGURATIONSPACESCENE_H
管理QGraphicsItem的容器
QGraphicsScene继承自QObject,而不是QWidget,因此本身不可见
基于迭代器访问的数据链表
QVector、Qlist、QlinkedList 类:用法比较
QlinkedList使用迭代器访问,而不是索引:
如果需要一个真实的链表,保证在列表中间插入常量时间,并将迭代器设置为项而不是索引,请使用QLinkedList.
size_t 基本的与机器相关的无符号整数的C/C + +类型
QGraphicsRectItem
QGraphicsSceneMouseEvent 鼠标移动
单独地向刚体添加碰撞对象,可以使用addCollision函数。
#ifndef CONFIGURATIONSPACETHREAD_H #define CONFIGURATIONSPACETHREAD_H #include <QThread> #include <rl/plan/Model.h> class ConfigurationSpaceThread : public QThread { Q_OBJECT public: ConfigurationSpaceThread(QObject* parent = nullptr); virtual ~ConfigurationSpaceThread(); void run(); void stop(); std::size_t axis0; std::size_t axis1; rl::math::Real delta0; rl::math::Real delta1; rl::plan::Model* model; protected: private: bool running; signals: void addCollision(const qreal& x, const qreal& y, const qreal& w, const qreal& h, const int& rgb); }; #endif // CONFIGURATIONSPACETHREAD_H
QThread 线程
#include <QMutexLocker> #include <rl/plan/SimpleModel.h> #include "ConfigurationSpaceThread.h" #include "MainWindow.h" ConfigurationSpaceThread::ConfigurationSpaceThread(QObject* parent) : QThread(parent), axis0(0), axis1(1), delta0(1.0f), delta1(1.0f), model(nullptr), running(false) { } ConfigurationSpaceThread::~ConfigurationSpaceThread() { } void ConfigurationSpaceThread::run() { QMutexLocker lock(&MainWindow::instance()->mutex); this->running = true; if (rl::plan::SimpleModel* model = dynamic_cast<rl::plan::SimpleModel*>(this->model)) { rl::math::Vector maximum = model->getMaximum(); rl::math::Vector minimum = model->getMinimum(); rl::math::Real range0 = std::abs(maximum(this->axis0) - minimum(this->axis0)); rl::math::Real range1 = std::abs(maximum(this->axis1) - minimum(this->axis1)); rl::math::Real delta0 = range0 / std::ceil(range0 / this->delta0); rl::math::Real delta1 = range1 / std::ceil(range1 / this->delta1); std::size_t steps0 = static_cast<std::size_t>(std::ceil(range0 / delta0)); std::size_t steps1 = static_cast<std::size_t>(std::ceil(range1 / delta1)); rl::math::Vector q(*MainWindow::instance()->q); for (std::size_t i = 0; i < steps1 + 1 && this->running; ++i) { q(this->axis1) = maximum(this->axis1) - i * delta1; for (std::size_t j = 0; j < steps0 + 1 && this->running; ++j) { q(this->axis0) = minimum(this->axis0) + j * delta0; model->setPosition(q); model->updateFrames(); if (model->isColliding()) { emit addCollision( q(this->axis0), q(this->axis1), delta0, delta1, 0 ); } } } } this->running = false; } void ConfigurationSpaceThread::stop() { if (this->running) { this->running = false; while (!this->isFinished()) { QThread::usleep(0); } } }
QMutexLocker 互斥锁解锁
QMutexLocker创建时将传入的QMutex锁定,释放时将传入的QMutex解锁。
run()函数中实现线程任务.
#ifndef GRAPHICSVIEW_H #define GRAPHICSVIEW_H #include <QGraphicsView> #include <QModelIndex> class GraphicsView : public QGraphicsView { Q_OBJECT public: GraphicsView(QWidget* parent = nullptr); virtual ~GraphicsView(); public slots: void adjust(); void adjust(const QModelIndex&, const QModelIndex&); protected: virtual void resizeEvent(QResizeEvent* event); private: }; #endif // GRAPHICSVIEW_H
QGraphicsView 视图窗口部件
将鼠标和按键事件场景化-使场景内容可视化
slots 槽函数
C++成员函数,很多的信号与之相关联,关联信号被发射时,槽就会被调用。
信号和槽是Qt特有的信息传输机制,让互不干扰的对象形成联系。
resizeEvent() 窗口大小、位置及其大小改变
adjust() 自动识别调整
直接使用adjust()函数,进行界面的实时调整。
#include "GraphicsView.h" GraphicsView::GraphicsView(QWidget* parent) : QGraphicsView(parent) { } GraphicsView::~GraphicsView() { } void GraphicsView::adjust() { this->fitInView(this->scene()->sceneRect(), Qt::KeepAspectRatio); } void GraphicsView::adjust(const QModelIndex&, const QModelIndex&) { this->adjust(); } void GraphicsView::resizeEvent(QResizeEvent* event) { this->adjust(); }
fitInView 适中view显示
视图中显示的内容较多时,出现横或竖的滚动条时,需要将视图中的元素适中显示时(即让滚动条因内容自动消失),通过计算出一个rect,调用fitInView函数即可。
#ifndef SOGRADIENTBACKGROUND_H #define SOGRADIENTBACKGROUND_H #include <Inventor/fields/SoSFColor.h> #include <Inventor/nodes/SoNode.h> class SoGradientBackground : public SoNode { SO_NODE_HEADER(SoGradientBackground); public: SoGradientBackground(); virtual SbBool affectsState() const; static void exitClass(); virtual void GLRender(SoGLRenderAction* action); static void initClass(); SoSFColor color0; SoSFColor color1; protected: virtual ~SoGradientBackground(); private: }; #endif // SOGRADIENTBACKGROUND_H
#ifdef WIN32 #include <windows.h> #endif // WIN32 #ifdef __APPLE__ #include <OpenGL/gl.h> #else // __APPLE__ #include <GL/gl.h> #endif // __APPLE__ #include <Inventor/nodes/SoSubNode.h> #include "SoGradientBackground.h" SO_NODE_SOURCE(SoGradientBackground); SoGradientBackground::SoGradientBackground() : SoNode(), color0(), color1() { SO_NODE_CONSTRUCTOR(SoGradientBackground); SO_NODE_ADD_FIELD(color0, (1.0f, 1.0f, 1.0f)); SO_NODE_ADD_FIELD(color1, (0.0f, 0.0f, 0.0f)); } SoGradientBackground::~SoGradientBackground() { } SbBool SoGradientBackground::affectsState() const { return false; } void SoGradientBackground::exitClass() { } void SoGradientBackground::GLRender(SoGLRenderAction* action) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); glColor3f(this->color0.getValue()[0], this->color0.getValue()[1], this->color0.getValue()[2]); glVertex2f(1.0, 1.0); glVertex2f(-1.0, 1.0); glColor3f(this->color1.getValue()[0], this->color1.getValue()[1], this->color1.getValue()[2]); glVertex2f(-1.0, -1.0); glVertex2f(1.0, -1.0); glEnd(); glPopAttrib(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } void SoGradientBackground::initClass() { SO_NODE_INIT_CLASS(SoGradientBackground, SoNode, "Node"); }
引用使用了SoQt库
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。