目录

一、功能需求

二、实现效果

三、实现方法


一、功能需求

3D测量软件中,需要在轮廓上进行二次编程,需要显示轮廓线,然后可以调节矩形框的范围的获取参数,如华汉的HyperShape3D软件,对轮廓的编程界面如下。

二、实现效果

2个矩形框 + 1个轮廓

1个矩形框 + 1个轮廓

三、实现方法

找到了一篇比较符合需求的博客,基于QChartView实现;

Qt Charts使用(重写QChartView,实现一些自定义功能)_讳疾忌医丶的博客-CSDN博客_qtcharts使用

该文中重写了paintEvent(QPaintEvent *event),绘制2个矩形框。然而当我需要添加更多的矩形框时,发现需要添加很多重复性的代码,扩展性极差。为此我在此基础上做了改进,QChartView是基于qt的Graphics/View框架实现的,因此我可以将矩形框封装成一个图元QGraphicsItem,然后在场景中添加图元。

关键代码如下

自定义QChartView

#ifndef MYCHARTS_H
#define MYCHARTS_H#include <QWidget>
#include <QtCharts/QLineSeries>
#include <QtCharts/QValueAxis>
#include <QChart>
#include <QChartView>
#include "processpropertyeditor_global.h"QT_CHARTS_USE_NAMESPACEclass GraphicsRangeRectItem;
class PROCESSPROPERTYEDITORSHARED_EXPORT ContourChartView : public QChartView
{Q_OBJECT
public:enum ItemTheme{LightPink = 0, /* 浅粉红 */Violet,        /* 紫罗兰 */SkyBlue,       /* 天蓝色 */Cyan,          /* 青色 */SeaGreen,      /* 海洋绿 */Yellow,        /* 纯黄 */Gold,          /* 金 */LightGrey,     /* 浅灰色 */};explicit ContourChartView(QWidget *parent = nullptr);GraphicsRangeRectItem *addItem(ItemTheme theme, const QPointF &topleft);void lineSeriesAppend(const QList<QPointF> &points);protected:void paintEvent(QPaintEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;void contextMenuEvent(QContextMenuEvent *event) override;public:QMap<ItemTheme, QColor > m_colors;QLineSeries *m_pSeries;QChart *m_pChart;
};//
#include "ContourChartView.h"
#include "GraphicsRangeRectItem.h"#include <QMenu>
#include <QDebug>
#include <QtMath>ContourChartView::ContourChartView(QWidget *parent): QChartView(parent)
{int a = 100;m_colors.insert(ItemTheme::LightPink, QColor(255, 182, 193, a));m_colors.insert(ItemTheme::Violet, QColor(238, 130, 238, a));m_colors.insert(ItemTheme::SkyBlue, QColor(135, 206, 235, a));m_colors.insert(ItemTheme::Cyan, QColor(0, 255, 255, a));m_colors.insert(ItemTheme::SeaGreen, QColor(46, 139, 87, a));m_colors.insert(ItemTheme::Yellow, QColor(255, 255, 0, a));m_colors.insert(ItemTheme::Gold, QColor(255, 215, 0, a));m_colors.insert(ItemTheme::LightGrey, QColor(211, 211, 211, a));m_pSeries = new QLineSeries();m_pSeries->setUseOpenGL(true);m_pChart = new QChart();m_pChart->setTheme(QChart::ChartThemeDark);m_pChart->legend()->hide();this->setChart(m_pChart);this->setRenderHints(QPainter::Antialiasing);
}GraphicsRangeRectItem *ContourChartView::addItem(ContourChartView::ItemTheme theme,const QPointF &topleft)
{GraphicsRangeRectItem *rectItem = new GraphicsRangeRectItem;rectItem->setRect(QRectF(topleft,  QSizeF(60, 700)));rectItem->setPen(QPen(QColor(205, 104, 57, 100)));rectItem->setBrush(m_colors.value(theme));rectItem->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);rectItem->setZValue(100);this->scene()->addItem(rectItem);return rectItem;
}void ContourChartView::lineSeriesAppend(const QList<QPointF> &points)
{QList<QAbstractSeries *>series =  m_pChart->series();if(series.contains(m_pSeries)){m_pChart->removeSeries(m_pSeries);}m_pSeries->clear();m_pSeries->append(points);m_pChart->addSeries(m_pSeries);m_pChart->createDefaultAxes();
}void ContourChartView::paintEvent(QPaintEvent *event)
{QChartView::paintEvent(event);
}void ContourChartView::mousePressEvent(QMouseEvent *event)
{QChartView::mousePressEvent(event);
}void ContourChartView::mouseMoveEvent(QMouseEvent *event)
{QChartView::mouseMoveEvent(event);
}void ContourChartView::mouseReleaseEvent(QMouseEvent *event)
{QChartView::mouseReleaseEvent(event);
}void ContourChartView::contextMenuEvent(QContextMenuEvent *event)
{QMenu menu(this);menu.addAction(QStringLiteral("放大"), [ = ](){chart()->zoom(1.2);});menu.addAction(QStringLiteral("缩小"), [ = ](){chart()->zoom(0.8);});menu.addAction(QStringLiteral("还原"), [ = ](){chart()->zoomReset();});menu.exec(event->globalPos());
}

自定义矩形框图元

#ifndef GRAPHICSRANGERECTITEM_H
#define GRAPHICSRANGERECTITEM_H#include <QGraphicsRectItem>class GraphicsRangeRectItem: public QObject, public QGraphicsRectItem
{Q_OBJECTpublic:enum E_HandleFlag : int{Default = 0x00,AtLeft = 0x01,AtRight = 0x02,AtCenter = 0x03};explicit GraphicsRangeRectItem(QGraphicsItem *parent = Q_NULLPTR);~GraphicsRangeRectItem();signals:void stateChanged();protected:virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;private:E_HandleFlag handleAt(const QPointF &pos);private:QMap<E_HandleFlag, Qt::CursorShape> handleCursors;E_HandleFlag handleSelected = Default;const int MIN_BOX_WIDTH = 20;
};#endif // GRAPHICSRANGERECTITEM_H//#include "GraphicsRangeRectItem.h"
#include <QCursor>
#include <QGraphicsSceneHoverEvent>
#include <QDebug>
#include <QGraphicsScene>
#include <QGraphicsView>GraphicsRangeRectItem::GraphicsRangeRectItem(QGraphicsItem *parent): QGraphicsRectItem(parent)
{handleCursors[Default] = Qt::ArrowCursor;handleCursors[AtLeft] = Qt::SizeHorCursor;handleCursors[AtRight] = Qt::SizeHorCursor;this->setFlags(QGraphicsItem::ItemIsSelectable |QGraphicsItem::ItemIsFocusable);setAcceptHoverEvents(true);
}GraphicsRangeRectItem::~GraphicsRangeRectItem()
{}void GraphicsRangeRectItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{if(this->isSelected()){E_HandleFlag handle = this->handleAt(event->pos());this->setCursor(QCursor(handleCursors.value(handle)));}QGraphicsRectItem::hoverMoveEvent(event);
}void GraphicsRangeRectItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{this->setCursor(QCursor(Qt::ArrowCursor));QGraphicsRectItem::hoverLeaveEvent(event);
}void GraphicsRangeRectItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{handleSelected = this->handleAt(event->pos());QGraphicsRectItem::mousePressEvent(event);
}void GraphicsRangeRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{switch (handleSelected){case E_HandleFlag::AtLeft:{QRectF oldRect = this->rect();/* 最小宽度限制 */if(oldRect.right() - event->pos().x() < MIN_BOX_WIDTH){return;}QRectF newRect = oldRect;newRect.setLeft(event->pos().x());this->setRect(newRect);update();}break;case E_HandleFlag::AtRight:{QRectF oldRect = this->rect();/* 最小宽度限制 */if(event->pos().x() - oldRect.left() < MIN_BOX_WIDTH){return;}QRectF newRect = oldRect;newRect.setRight(event->pos().x());this->setRect(newRect);update();}break;case E_HandleFlag::AtCenter:{QRectF oldRect = this->rect();/* 防止超出左右边界 */int leftLimit = 0;int rightLimit = this->scene()->views().at(0)->size().width();if(event->pos().x() <= leftLimit || event->pos().x() >= rightLimit){return;}QRectF newRect = oldRect;newRect.moveCenter(QPointF(event->pos().x(), oldRect.center().y()));this->setRect(newRect);update();}break;default:break;}
}void GraphicsRangeRectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{QGraphicsItem::mouseReleaseEvent(event);handleSelected = Default;if(event->button() == Qt::LeftButton){emit stateChanged();}this->update();
}GraphicsRangeRectItem::E_HandleFlag GraphicsRangeRectItem::handleAt(const QPointF &pos)
{QRectF rect = this->rect();static const int check_radius = 3;if (std::abs(pos.x() - rect.right()) < check_radius){return E_HandleFlag::AtRight;}else if (std::abs(pos.x() - rect.left()) < check_radius){return E_HandleFlag::AtLeft;}else if(rect.contains(pos)){return E_HandleFlag::AtCenter;}return E_HandleFlag::Default;
}

使用

创建窗口

ContourChartView *graphicsView = new ContourChartView();

添加轮廓

graphicsView->lineSeriesAppend(const QList<QPointF> &points);

添加矩形框

GraphicsRangeRectItem *rectItem1 = chartView()->addItem(ContourChartView::ItemTheme::LightPink, QPointF(100, 10));
    rectItem1->setToolTip(QStringLiteral("基准对象"));
 GraphicsRangeRectItem *rectItem2 = chartView()->addItem(ContourChartView::ItemTheme::Violet, QPointF(400, 10));
    rectItem2->setToolTip(QStringLiteral("测量对象"));
    
坐标映射,需要将场景中的坐标转换到chart图表上的坐标值
    connect(rectItem1, &GraphicsRangeRectItem::stateChanged, this, [ = ]()
    {
    double xl = chartView()->chart()->mapToValue(QPointF(rectItem1->rect().left(),  0)).x();
    double xr = chartView()->chart()->mapToValue(QPointF(rectItem1->rect().right(), 0)).x();
    });

轮廓图编程-自定义QChartView相关推荐

  1. 使用NCL绘制安徽省的轮廓图

    使用NCL绘制安徽省的轮廓图,其它省可以参照设置: load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl" load &q ...

  2. Android显示九宫图(自定义圆角,仿微信九宫格图)

    详细解析Android显示九宫图(自定义圆角,仿微信九宫格图) 这是一个自定义九宫格图片框架,里面有设置圆角大小,还有当图片一张的时候控件自定义的大小,图片的间隔,四张图片的时候图片自定义为两行两列等 ...

  3. plotly.js 常见图形使用 常见图形操作 折线图 热力图 轮廓图 泡泡图 图点击事件

    这篇文章内容来自自己工作中用到的可视化操作,偏向于科学图表方面.网上资料多且杂,并且有的并不准确,不过如果时间充足,推荐看plotly.js的英文官网,也提供搜索功能,只是需要对图表很熟悉并且英文要好 ...

  4. Qt编写地图综合应用41-在线轮廓图

    一.前言 轮廓图也叫行政区划,这里的轮廓图是指百度地图的区域轮廓图,不是之前文章中提到的echart专用的轮廓图,百度地图的轮廓图就是一个不规则的多边形区域,只不过这个区域的坐标点一般是特别多的,比如 ...

  5. Qt编写地图综合应用42-离线轮廓图

    一.前言 离线轮廓图使用起来,就没有在线轮廓图方便了,在线的可以直接传入名称拿到,离线的只能自己绘制了,一般需要用区域轮廓图下载器将你需要的区域下载好对应的js文件,其实就是一堆坐标点集合数组,这些数 ...

  6. 使用Python绘制6.1儿童节消消乐,素描图,词云图,字符画图,提取轮廓图及蒙太奇效果图

    这篇博客将介绍如何使用Python绘制6.1儿童节消消乐,素描图,词云图,字符画图,提取轮廓图及蒙太奇效果图. 使用Python绘制端午dragboat消消乐 美轮美奂的界面效果 1. 效果图 6.1 ...

  7. Python使用matplotlib函数subplot可视化多个不同颜色的折线图、自定义数据点的形状、自定义折线图的颜色

    Python使用matplotlib函数subplot可视化多个不同颜色的折线图.自定义数据点的形状.自定义折线图的颜色 目录

  8. R语言使用ggplot2包使用geom_density()函数绘制分组密度图(自定义调色板、brewer、灰度比例)实战(density plot)

    R语言使用ggplot2包使用geom_density()函数绘制分组密度图(自定义调色板.brewer.灰度比例)实战(density plot) 目录 R语言使用ggplot2包使用geom_de ...

  9. R语言使用ggradar包可视化基本雷达图(radar chart、蜘蛛图spider plot)、可视化单个数据对象的雷达图、自定义雷达图的线条类型、线条宽度、数据点大小、色彩等

    R语言使用ggradar包可视化基本雷达图(radar chart.蜘蛛图spider plot).可视化单个数据对象的雷达图.自定义雷达图的线条类型.线条宽度.数据点大小.色彩等(Customize ...

最新文章

  1. 提升 Node.js 应用性能的 5 个技巧
  2. js函数调用html对象参数传递参数吗,js里函数参数传递对象传的是指针吗
  3. harbor镜像仓库-https访问的证书配置 (docker配置harbor https证书)
  4. telnet或SQLplus下命令输入错误如何删掉重新输入
  5. P3369-[模板]普通平衡树【替罪羊树】
  6. python的注释符_Python3 注释和运算符
  7. 如何执行字符串的PHP代码
  8. ThreadLocal原理和用法
  9. sql 查找重复数据,并且重复数据有子集
  10. Linux下编译(安装)程序、编译库整理
  11. 企业邮箱服务器如何设置?
  12. python 白色怎么表示_在numpy中创建“白色”图像(2D图像)
  13. 2023年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多
  14. PHP 生成随机昵称或用户名
  15. 智能制造 | 机器视觉系统,直击纺织行业人工质检痛点难点,提升缺陷检出精准度至99.9%
  16. Oracle查询CLOB类型字段的内容:
  17. Cypress Commands – UI Interaction Commands
  18. 一键如何完成多张静态图合成GIF图?
  19. activiti 流程实例与业务关联
  20. 微信小程序控制台警告WXMLRT_$gwx:./wxParse/wxParse.wxml:block:102:18: wx:key=““ does not look lik

热门文章

  1. hfs2.3中文版快速搭建http文件下载服务器系统——墨涩网
  2. virtual box上安装ubuntu20.04遇到的问题
  3. python 读取文件去除回车
  4. Java探针技术详解
  5. 通达信量化接口主力进出指标分析
  6. 音频数据格式:PCM,WAV,MIDI
  7. 推荐免费的svn空间
  8. vh布局移动端软键盘弹起改变高度问题
  9. KindEditor 自定义插件
  10. 解决问题:Oracle存储过程执行成功,但数据没有变化