轮廓图编程-自定义QChartView
目录
一、功能需求
二、实现效果
三、实现方法
一、功能需求
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相关推荐
- 使用NCL绘制安徽省的轮廓图
使用NCL绘制安徽省的轮廓图,其它省可以参照设置: load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl" load &q ...
- Android显示九宫图(自定义圆角,仿微信九宫格图)
详细解析Android显示九宫图(自定义圆角,仿微信九宫格图) 这是一个自定义九宫格图片框架,里面有设置圆角大小,还有当图片一张的时候控件自定义的大小,图片的间隔,四张图片的时候图片自定义为两行两列等 ...
- plotly.js 常见图形使用 常见图形操作 折线图 热力图 轮廓图 泡泡图 图点击事件
这篇文章内容来自自己工作中用到的可视化操作,偏向于科学图表方面.网上资料多且杂,并且有的并不准确,不过如果时间充足,推荐看plotly.js的英文官网,也提供搜索功能,只是需要对图表很熟悉并且英文要好 ...
- Qt编写地图综合应用41-在线轮廓图
一.前言 轮廓图也叫行政区划,这里的轮廓图是指百度地图的区域轮廓图,不是之前文章中提到的echart专用的轮廓图,百度地图的轮廓图就是一个不规则的多边形区域,只不过这个区域的坐标点一般是特别多的,比如 ...
- Qt编写地图综合应用42-离线轮廓图
一.前言 离线轮廓图使用起来,就没有在线轮廓图方便了,在线的可以直接传入名称拿到,离线的只能自己绘制了,一般需要用区域轮廓图下载器将你需要的区域下载好对应的js文件,其实就是一堆坐标点集合数组,这些数 ...
- 使用Python绘制6.1儿童节消消乐,素描图,词云图,字符画图,提取轮廓图及蒙太奇效果图
这篇博客将介绍如何使用Python绘制6.1儿童节消消乐,素描图,词云图,字符画图,提取轮廓图及蒙太奇效果图. 使用Python绘制端午dragboat消消乐 美轮美奂的界面效果 1. 效果图 6.1 ...
- Python使用matplotlib函数subplot可视化多个不同颜色的折线图、自定义数据点的形状、自定义折线图的颜色
Python使用matplotlib函数subplot可视化多个不同颜色的折线图.自定义数据点的形状.自定义折线图的颜色 目录
- R语言使用ggplot2包使用geom_density()函数绘制分组密度图(自定义调色板、brewer、灰度比例)实战(density plot)
R语言使用ggplot2包使用geom_density()函数绘制分组密度图(自定义调色板.brewer.灰度比例)实战(density plot) 目录 R语言使用ggplot2包使用geom_de ...
- R语言使用ggradar包可视化基本雷达图(radar chart、蜘蛛图spider plot)、可视化单个数据对象的雷达图、自定义雷达图的线条类型、线条宽度、数据点大小、色彩等
R语言使用ggradar包可视化基本雷达图(radar chart.蜘蛛图spider plot).可视化单个数据对象的雷达图.自定义雷达图的线条类型.线条宽度.数据点大小.色彩等(Customize ...
最新文章
- 提升 Node.js 应用性能的 5 个技巧
- js函数调用html对象参数传递参数吗,js里函数参数传递对象传的是指针吗
- harbor镜像仓库-https访问的证书配置 (docker配置harbor https证书)
- telnet或SQLplus下命令输入错误如何删掉重新输入
- P3369-[模板]普通平衡树【替罪羊树】
- python的注释符_Python3 注释和运算符
- 如何执行字符串的PHP代码
- ThreadLocal原理和用法
- sql 查找重复数据,并且重复数据有子集
- Linux下编译(安装)程序、编译库整理
- 企业邮箱服务器如何设置?
- python 白色怎么表示_在numpy中创建“白色”图像(2D图像)
- 2023年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多
- PHP 生成随机昵称或用户名
- 智能制造 | 机器视觉系统,直击纺织行业人工质检痛点难点,提升缺陷检出精准度至99.9%
- Oracle查询CLOB类型字段的内容:
- Cypress Commands – UI Interaction Commands
- 一键如何完成多张静态图合成GIF图?
- activiti 流程实例与业务关联
- 微信小程序控制台警告WXMLRT_$gwx:./wxParse/wxParse.wxml:block:102:18: wx:key=““ does not look lik