当前位置:网站首页>Qt Charts使用(重写QChartView,实现一些自定义功能)
Qt Charts使用(重写QChartView,实现一些自定义功能)
2022-07-07 05:48:00 【xiaozhu丶】

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_OBJECT
public:
explicit mycharts(QWidget *parent = nullptr);
public:
//鼠标在区域的哪个位置
enum AreaPosition : int
{
Outside = 0x00,
Inside = 0xFF, //任意值
AtLeft = 0x01,
AtRight = 0x02,
AtTop = 0x10,
AtBottom = 0x20,
AtTopLeft = 0x11, //AtLeft|AtTop
AtTopRight = 0x12, //AtRight|AtTop
AtBottomLeft = 0x21, //AtLeft|AtBottom
AtBottomRight = 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,绘制时整体宽度先减去1px
QRect 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};
int m_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);
//无选区,或者不在选区判定范围则返回outside
if (!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);
//无选区,或者不在选区判定范围则返回outside
if (!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;
}
}
边栏推荐
- [untitled]
- A method for quickly viewing pod logs under frequent tests (grep awk xargs kuberctl)
- 调用华为游戏多媒体服务的创建引擎接口返回错误码1002,错误信息:the params is error
- [kuangbin]专题十五 数位DP
- SSM integration
- BiSeNet的特點
- IELTS review progress and method use [daily revision]
- Rainbow 5.7.1 supports docking with multiple public clouds and clusters for abnormal alarms
- MES系統,是企業生產的必要選擇
- Learn how to compile basic components of rainbow from the source code
猜你喜欢

Download and install orcale database11.2.0.4

Give full play to the wide practicality of maker education space

DeiT学习笔记

Famine cloud service management script

How to integrate app linking services in harmonyos applications

快速集成认证服务-HarmonyOS平台
![[Yu Yue education] higher vocational English reference materials of Nanjing Polytechnic University](/img/e2/519a5267cd5425a83434d2da65ebe6.jpg)
[Yu Yue education] higher vocational English reference materials of Nanjing Polytechnic University

Caractéristiques de bisenet

One click installation of highly available Nacos clusters in rainbow

【无标题】
随机推荐
调用华为游戏多媒体服务的创建引擎接口返回错误码1002,错误信息:the params is error
Opencv learning note 5 - gradient calculation / edge detection
grpc、oauth2、openssl、双向认证、单向认证等专栏文章目录
如何在快应用中实现滑动操作组件
Open3D ISS关键点
Rainbow combines neuvector to practice container safety management
[machine learning] watermelon book data set_ data sharing
AVL balanced binary search tree
Deit learning notes
Analyzing the influence of robot science and technology development concept on Social Research
GFS distributed file system
Ebpf cilium practice (2) - underlying network observability
Implementation of navigation bar at the bottom of applet
Automatic upgrading of database structure in rainbow
Splunk中single value视图使用将数值替换为文字
Ebpf cilium practice (1) - team based network isolation
Tuowei information uses the cloud native landing practice of rainbow
国标GB28181协议视频平台EasyGBS新增拉流超时配置
A single game with goods increased by 100000, and the rural anchor sold men's clothes on top of the list?
如何在HarmonyOS应用中集成App Linking服务