第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > Qt Charts使用(重写QChartView 实现一些自定义功能)

Qt Charts使用(重写QChartView 实现一些自定义功能)

时间:2024-05-13 21:16:13

相关推荐

Qt Charts使用(重写QChartView 实现一些自定义功能)

文章目录

1、charts简单使用2、重写QChartView

1、charts简单使用

QLineSeries* m_pSeries = new QLineSeries();QFile file("C:\\Users\\Administrator\\Desktop\\2.txt");file.open(QIODevice::ReadOnly | QIODevice::Text);QTextStream in(&file);while (!in.atEnd()){QString line = in.readLine();QStringList listLine = line.split("\t");// 从文件读取数据m_pSeries->append(listLine[0].toDouble(), listLine[1].toDouble());}file.close();// QChartView *m_pChartView = new QChartView(this);// 用重写QChartView做显示mycharts* m_pChartView = new mycharts(this);QChart* m_pChart = new QChart();m_pChart->addSeries(m_pSeries);m_pSeries->setUseOpenGL(true);m_pChart->createDefaultAxes();m_pChart->axes(Qt::Vertical).at(0)->setRange(-240, 240);m_pChart->axisX()->setRange(-160,160);m_pChart->legend()->hide();m_pChartView->setChart(m_pChart);m_pChartView->resize(QSize(600, 500));m_pChartView->setRenderHints(QPainter::Antialiasing);

2、重写QChartView

注意:提升性能方案

m_pSeries->setUseOpenGL(true);

不使用openGL时,3000个点左右就卡死,在上绘制会更卡,性能提升有限,提升了10倍左右

mycharts.h

#ifndef MYCHARTS_H#define MYCHARTS_H#include <QWidget>#include <QtCharts/QLineSeries>#include <QtCharts/QValueAxis>#include <QChart>#include <QChartView>QT_CHARTS_USE_NAMESPACE#include "mainwindow.h"class mycharts : public QChartView{Q_OBJECTpublic:explicit mycharts(QWidget *parent = nullptr);public://鼠标在区域的哪个位置enum AreaPosition : int{Outside = 0x00,Inside = 0xFF, //任意值AtLeft = 0x01,AtRight = 0x02,AtTop = 0x10,AtBottom = 0x20,AtTopLeft = 0x11, //AtLeft|AtTopAtTopRight = 0x12, //AtRight|AtTopAtBottomLeft = 0x21, //AtLeft|AtBottomAtBottomRight = 0x22 //AtRight|AtBottom};//当前编辑类型enum EditType : int{EditNone, //无操作PressInside, //在选区范围内按下PressOutside, //在选区范围外按下DrawSelection, //绘制MoveSelection, //拖动EditSelection //拉伸编辑};protected:void paintEvent(QPaintEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;private://计算鼠标相对区域的位置AreaPosition calcPosition(const QPoint &pos);AreaPosition calcPosition1(const QPoint &pos);//当前鼠标对应选区的位置void setCurPosition(AreaPosition position);void setCurPosition1(AreaPosition position);//根据鼠标当前位置更新鼠标样式void updateCursor();void updateCursor1();private://当前选区//QRect有四个成员变量,分别对应左上角和右下角点坐标//x1-左上角坐标x//x2-等于x1+width-1//y1-左上角坐标y//y2-等于y1+height-1//即QRect(50,50,200,200)时,topLeft=(50,50)bottomRight=(249,249)//fillRect会填充整个区域//drawRect在画笔宽度奇数时,右下角会多1px,绘制时整体宽度先减去1pxQRect selection;QRect select1;//是否有选区bool hasSelection{false};//鼠标当前操作位置AreaPosition curPosition{AreaPosition::Outside};AreaPosition curPosition1{AreaPosition::Outside };//当前操作类型EditType curEditType{EditType::EditNone};EditType curEditType1{EditType::EditNone };//鼠标按下标志bool pressFlag{false};bool pressFlag1{false };//鼠标按下位置QPoint pressPos;//目前用于记录press时鼠标与选区左上角的坐标差值QPoint tempPos;QPoint tempPos1;//鼠标当前位置QPoint mousePos;//最小宽度static const int Min_Width{5};intm_xl;int m_yl;int m_xr;int m_yr;MainWindow*m_pwindows;signals:public slots:};#endif // MYCHARTS_H

QChartView.cpp

#include "mycharts.h"#include <qdebug.h>mycharts::mycharts(QWidget *parent) : QChartView(parent){m_pwindows = (MainWindow*)parent;setMouseTracking(true);selection = QRect(85, 37, 60, 415);hasSelection = true;select1 = QRect(400, 37,60,415);}void mycharts::paintEvent(QPaintEvent *event){QChartView::paintEvent(event);QPainter painter(viewport());if (!hasSelection)return;painter.save();if (pressFlag && curPosition != AreaPosition::Outside){//点击样式,选用纯正的原谅绿主题//painter.setPen(QColor(0, 255, 255));painter.setPen(QColor(205,104,57,100));painter.setBrush(QColor(46, 139, 87, 100));}else if (curPosition != AreaPosition::Outside){//悬停样式painter.setPen(QColor(0, 255, 255,100));painter.setBrush(QColor(46, 139, 87, 100));}else{//未选中样式painter.setPen(QColor(0, 150, 255,100));painter.setBrush(QColor(46,139,87,100));}//-1是为了边界在rect范围内painter.drawRect(selection.adjusted(0, 0, -1, -1));if (pressFlag1 && curPosition1 != AreaPosition::Outside){//点击样式,选用纯正的原谅绿主题//painter.setPen(QColor(0, 255, 255));painter.setPen(QColor(205, 104, 57,150));painter.setBrush(QColor(205, 104, 57,100));}else if (curPosition1 != AreaPosition::Outside){//悬停样式painter.setPen(QColor(139,115,85,100));//painter.setBrush(QColor(0, 160, 0));painter.setBrush(QColor(205, 104, 57, 100));}else{//未选中样式painter.setPen(QColor(255,231,186,100));//painter.setBrush(QColor(0, 140, 0));painter.setBrush(QColor(205, 104, 57, 100));}painter.drawRect(select1.adjusted(0, 0, -1, -1));painter.restore();}void mycharts::mousePressEvent(QMouseEvent *event){QChartView::mousePressEvent(event);//event->accept();mousePos = event->pos();if (event->button() == Qt::LeftButton){pressFlag1 = true;//鼠标左键进行编辑操作pressFlag = true;pressPos = event->pos();if (curPosition == AreaPosition::Inside){curEditType = PressInside;//鼠标相对选区左上角的位置tempPos = mousePos - selection.topLeft();//tempPos1 = mousePos - select1.topLeft();}else if (curPosition != AreaPosition::Outside){curEditType = EditSelection;}else{curEditType = PressOutside;}if (curPosition1 == AreaPosition::Inside){curEditType1 = PressInside;tempPos1 = mousePos - select1.topLeft();}else if (curPosition1 != AreaPosition::Outside){curEditType1 = EditSelection;}else{curEditType1 = PressOutside;}}else{//非单独按左键时的操作}update();}void mycharts::mouseMoveEvent(QMouseEvent *event){//qDebug() << this->chart()->mapToValue(event->pos());//qDebug() << this->chart()->mapToValue(QPointF(QPoint(selection.left(),0))).x();//qDebug() << this->chart()->mapToValue(QPointF(QPoint(selection.right(), 0)));m_xl = this->chart()->mapToValue(QPointF(QPoint(selection.left(), 0))).x();m_yl = this->chart()->mapToValue(QPointF(QPoint(selection.right(), 0))).x();m_xr = this->chart()->mapToValue(QPointF(QPoint(select1.left(), 0))).x();m_yr = this->chart()->mapToValue(QPointF(QPoint(select1.right(), 0))).x();m_pwindows->setLine(m_xl, m_yl,m_xr,m_yr);QChartView::mouseMoveEvent(event);mousePos = event->pos();if (curEditType == MoveSelection && curEditType1 == MoveSelection)curEditType1 = PressOutside;if (pressFlag){if (curEditType == PressInside){//在选区内点击且移动,则移动选区if (QPoint(pressPos - mousePos).manhattanLength() > 3){curEditType = MoveSelection;}}QPoint mouse_p = mousePos;//限制范围在可视区域if (mouse_p.x() < 0){//mouse_p.setX(0);mouse_p.setX(0);}else if (mouse_p.x() > width() - 1){mouse_p.setX(width() - 1);}if (mouse_p.y() < 0){mouse_p.setY(0);}else if (mouse_p.y() > height() - 1){mouse_p.setY(height() - 1);}if (curEditType == DrawSelection){//根据按下时位置和当前位置确定一个选区selection = QRect(pressPos, mouse_p);}else if (curEditType == MoveSelection){//移动选区selection.moveTopLeft(mousePos - tempPos);//select1.moveTopLeft(mousePos - tempPos1);//限制范围在可视区域if (selection.left() < 73){//selection.moveLeft(0);selection.moveLeft(73);}else if (selection.right() > width() - 48){selection.moveRight(width() - 48);//selection.moveRight(450);}if (selection.top() < 37){selection.moveTop(37);}else if (selection.bottom() > height() - 53){//selection.moveBottom(height() - 1);selection.moveBottom(height() - 53);}}else if (curEditType == EditSelection){//拉伸选区边界int position = curPosition;if (position & AtLeft){if (mouse_p.x() < selection.right()){selection.setLeft(mouse_p.x());}else{selection.setLeft(selection.right() - 10);}}else if (position & AtRight){if (mouse_p.x() > selection.left()){selection.setRight(mouse_p.x());}else{selection.setRight(selection.left() + 10);}}}}else{setCurPosition(calcPosition(mousePos));}if (pressFlag1){if (curEditType1 == PressInside){if (QPoint(pressPos - mousePos).manhattanLength() > 3){curEditType1 = MoveSelection;}}QPoint mouse_p = mousePos;//限制范围在可视区域if (mouse_p.x() < 0){mouse_p.setX(0);}else if (mouse_p.x() > width() - 1){mouse_p.setX(width() - 1);}if (mouse_p.y() < 0){mouse_p.setY(0);}else if (mouse_p.y() > height() - 1){mouse_p.setY(height() - 1);}if (curEditType1 == DrawSelection){//根据按下时位置和当前位置确定一个选区select1 = QRect(pressPos, mouse_p);}else if (curEditType1 == MoveSelection){//移动选区select1.moveTopLeft(mousePos - tempPos1);//限制范围在可视区域if (select1.left() < 73){select1.moveLeft(73);}else if (select1.right() > width() - 48){select1.moveRight(width() - 48);}if (select1.top() < 37){select1.moveTop(37);}else if (select1.bottom() > height() - 53){select1.moveBottom(height() - 53);}}else if (curEditType1 == EditSelection){//拉伸选区边界int position = curPosition1;if (position & AtLeft){if (mouse_p.x() < select1.right()){select1.setLeft(mouse_p.x());}else{select1.setLeft(select1.right() - 10);}}else if (position & AtRight){if (mouse_p.x() > select1.left()){select1.setRight(mouse_p.x());}else{select1.setRight(select1.left() + 10);}}}}else{setCurPosition1(calcPosition1(mousePos));}update();}void mycharts::mouseReleaseEvent(QMouseEvent *event){QChartView::mouseReleaseEvent(event);//event->accept();mousePos = event->pos();pressFlag = false;pressFlag1 = false;if (curEditType != EditNone){//编辑结束后判断是否小于最小宽度,是则取消选区if (curEditType == DrawSelection){selection = selection.normalized();if (selection.width() < Min_Width || selection.height() < Min_Width){hasSelection = false;}}else if (curEditType == MoveSelection){}else if (curEditType == EditSelection){/* if (selection.width() < Min_Width || selection.height() < Min_Width){hasSelection = false;}*/}curEditType = EditNone;}setCurPosition(calcPosition(mousePos));if (curEditType1 != EditNone){if (curEditType1 == DrawSelection){select1 = select1.normalized();if (select1.width() < Min_Width || select1.height() < Min_Width){hasSelection = false;}}else if (curEditType1 == MoveSelection){}else if (curEditType1 == EditSelection){/* if (selection.width() < Min_Width || selection.height() < Min_Width){hasSelection = false;}*/}curEditType1 = EditNone;}setCurPosition1(calcPosition1(mousePos));update();}mycharts::AreaPosition mycharts::calcPosition(const QPoint &pos){//一条线太窄,不好触发,增加判断范围又会出现边界太近时交叠在一起//目前的策略是从右下开始判断,左上的优先级更低一点static const int check_radius = 3;int position = AreaPosition::Outside;QRect check_rect = selection.adjusted(-check_radius, -check_radius, check_radius-1, check_radius-1);//无选区,或者不在选区判定范围则返回outsideif (!hasSelection || !check_rect.contains(pos)){return (mycharts::AreaPosition)position;}//判断是否在某个边界上if (std::abs(pos.x() - selection.right()) < check_radius){position |= AreaPosition::AtRight;}else if (std::abs(pos.x() - selection.left()) < check_radius){position |= AreaPosition::AtLeft;}if (std::abs(pos.y() - selection.bottom()) < check_radius){position |= AreaPosition::AtBottom;}else if (std::abs(pos.y() - selection.top()) < check_radius){position |= AreaPosition::AtTop;}//没在边界上就判断是否在内部if (position == AreaPosition::Outside && selection.contains(pos)){position = AreaPosition::Inside;}return (mycharts::AreaPosition)position;}mycharts::AreaPosition mycharts::calcPosition1(const QPoint & pos){//一条线太窄,不好触发,增加判断范围又会出现边界太近时交叠在一起//目前的策略是从右下开始判断,左上的优先级更低一点static const int check_radius = 3;int position = AreaPosition::Outside;QRect check_rect = select1.adjusted(-check_radius, -check_radius, check_radius - 1, check_radius - 1);//无选区,或者不在选区判定范围则返回outsideif (!hasSelection || !check_rect.contains(pos)){return (mycharts::AreaPosition)position;}//判断是否在某个边界上if (std::abs(pos.x() - select1.right()) < check_radius){position |= AreaPosition::AtRight;}else if (std::abs(pos.x() - select1.left()) < check_radius){position |= AreaPosition::AtLeft;}if (std::abs(pos.y() - select1.bottom()) < check_radius){position |= AreaPosition::AtBottom;}else if (std::abs(pos.y() - select1.top()) < check_radius){position |= AreaPosition::AtTop;}//没在边界上就判断是否在内部if (position == AreaPosition::Outside && select1.contains(pos)){position = AreaPosition::Inside;}return (mycharts::AreaPosition)position;}void mycharts::setCurPosition(mycharts::AreaPosition position){if (position != curPosition){curPosition = position;updateCursor();}}void mycharts::setCurPosition1(AreaPosition position){if (position != curPosition1){curPosition1 = position;updateCursor1();}}void mycharts::updateCursor(){switch (curPosition){case AtLeft:case AtRight:setCursor(Qt::SizeHorCursor);break;case AtTop:case AtBottom:setCursor(Qt::SizeVerCursor);break;case AtTopLeft:case AtBottomRight:setCursor(Qt::SizeFDiagCursor);break;case AtTopRight:case AtBottomLeft:setCursor(Qt::SizeBDiagCursor);break;default:setCursor(Qt::ArrowCursor);break;}}void mycharts::updateCursor1(){switch (curPosition1){case AtLeft:case AtRight:setCursor(Qt::SizeHorCursor);break;case AtTop:case AtBottom:setCursor(Qt::SizeVerCursor);break;case AtTopLeft:case AtBottomRight:setCursor(Qt::SizeFDiagCursor);break;case AtTopRight:case AtBottomLeft:setCursor(Qt::SizeBDiagCursor);break;default:setCursor(Qt::ArrowCursor);break;}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。