当前位置:网站首页>QT charts use (rewrite qchartview to realize some custom functions)
QT charts use (rewrite qchartview to realize some custom functions)
2022-07-07 08:42:00 【Xiaozhu】
List of articles
1、charts Easy to use
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");
// Read data from file
m_pSeries->append(listLine[0].toDouble(), listLine[1].toDouble());
}
file.close();
// QChartView *m_pChartView = new QChartView(this);
// Rewrite with QChartView Display
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、 rewrite QChartView
Be careful : Performance improvement scheme
m_pSeries->setUseOpenGL(true);
Don't use openGL when ,3000 It will get stuck around one o'clock , Drawing on will be more card , Limited performance improvement , Promoted 10 About times
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:
// Where is the mouse in the area
enum AreaPosition : int
{
Outside = 0x00,
Inside = 0xFF, // Any value
AtLeft = 0x01,
AtRight = 0x02,
AtTop = 0x10,
AtBottom = 0x20,
AtTopLeft = 0x11, //AtLeft|AtTop
AtTopRight = 0x12, //AtRight|AtTop
AtBottomLeft = 0x21, //AtLeft|AtBottom
AtBottomRight = 0x22 //AtRight|AtBottom
};
// Current edit type
enum EditType : int
{
EditNone, // No operation
PressInside, // Press... Within the selection
PressOutside, // Press... Outside the selection area
DrawSelection, // draw
MoveSelection, // Drag the
EditSelection // Stretch edit
};
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
// Calculate the position of the mouse relative to the area
AreaPosition calcPosition(const QPoint &pos);
AreaPosition calcPosition1(const QPoint &pos);
// The position of the current mouse corresponding to the selected area
void setCurPosition(AreaPosition position);
void setCurPosition1(AreaPosition position);
// Updates the mouse style based on the current mouse position
void updateCursor();
void updateCursor1();
private:
// Current constituency
//QRect There are four member variables , Corresponding to the coordinates of the upper left corner and the lower right corner respectively
//x1- Top left coordinates x
//x2- be equal to x1+width-1
//y1- Top left coordinates y
//y2- be equal to y1+height-1
// namely QRect(50,50,200,200) when ,topLeft=(50,50)bottomRight=(249,249)
//fillRect Will fill the entire area
//drawRect When the brush width is odd , There will be more... In the lower right corner 1px, Subtract... From the overall width when drawing 1px
QRect selection;
QRect select1;
// Is there a constituency
bool hasSelection{
false};
// The current operating position of the mouse
AreaPosition curPosition{
AreaPosition::Outside};
AreaPosition curPosition1{
AreaPosition::Outside };
// Current operation type
EditType curEditType{
EditType::EditNone};
EditType curEditType1{
EditType::EditNone };
// Press the mouse button to mark
bool pressFlag{
false};
bool pressFlag1{
false };
// Mouse down position
QPoint pressPos;
// Currently used to record press The coordinate difference between the mouse and the upper left corner of the selection
QPoint tempPos;
QPoint tempPos1;
// Current mouse position
QPoint mousePos;
// Minimum width
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)
{
// Click on the style , Choose a pure green theme
//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)
{
// Hover style
painter.setPen(QColor(0, 255, 255,100));
painter.setBrush(QColor(46, 139, 87, 100));
}
else
{
// No style selected
painter.setPen(QColor(0, 150, 255,100));
painter.setBrush(QColor(46,139,87,100));
}
//-1 For the boundary in rect Within the scope of
painter.drawRect(selection.adjusted(0, 0, -1, -1));
if (pressFlag1 && curPosition1 != AreaPosition::Outside)
{
// Click on the style , Choose a pure green theme
//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)
{
// Hover style
painter.setPen(QColor(139,115,85,100));
//painter.setBrush(QColor(0, 160, 0));
painter.setBrush(QColor(205, 104, 57, 100));
}
else
{
// No style selected
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;
// Edit with the left mouse button
pressFlag = true;
pressPos = event->pos();
if (curPosition == AreaPosition::Inside)
{
curEditType = PressInside;
// The position of the mouse relative to the upper left corner of the selection
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
{
// Not the operation when pressing the left key alone
}
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)
{
// Click and move in the selection , Then move the selection
if (QPoint(pressPos - mousePos).manhattanLength() > 3)
{
curEditType = MoveSelection;
}
}
QPoint mouse_p = mousePos;
// Limit the scope to the visible area
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)
{
// Determine a selection according to the position when pressed and the current position
selection = QRect(pressPos, mouse_p);
}
else if (curEditType == MoveSelection)
{
// Moving constituencies
selection.moveTopLeft(mousePos - tempPos);
//select1.moveTopLeft(mousePos - tempPos1);
// Limit the scope to the visible area
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)
{
// Stretch the selection boundary
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;
// Limit the scope to the visible area
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)
{
// Determine a selection according to the position when pressed and the current position
select1 = QRect(pressPos, mouse_p);
}
else if (curEditType1 == MoveSelection)
{
// Moving constituencies
select1.moveTopLeft(mousePos - tempPos1);
// Limit the scope to the visible area
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)
{
// Stretch the selection boundary
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)
{
// After editing, judge whether it is less than the minimum width , If yes, cancel the constituency
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)
{
// One line is too narrow , It's not easy to trigger , Increasing the judgment range will overlap when the boundary is too close
// The current strategy is to judge from the bottom right , The upper left has a lower priority
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);
// No constituency , Or if it is not in the selection judgment range, it returns outside
if (!hasSelection || !check_rect.contains(pos))
{
return (mycharts::AreaPosition)position;
}
// Determine whether it is on a boundary
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;
}
// Judge whether it is inside without being on the boundary
if (position == AreaPosition::Outside && selection.contains(pos))
{
position = AreaPosition::Inside;
}
return (mycharts::AreaPosition)position;
}
mycharts::AreaPosition mycharts::calcPosition1(const QPoint & pos)
{
// One line is too narrow , It's not easy to trigger , Increasing the judgment range will overlap when the boundary is too close
// The current strategy is to judge from the bottom right , The upper left has a lower priority
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);
// No constituency , Or if it is not in the selection judgment range, it returns outside
if (!hasSelection || !check_rect.contains(pos))
{
return (mycharts::AreaPosition)position;
}
// Determine whether it is on a boundary
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;
}
// Judge whether it is inside without being on the boundary
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;
}
}
边栏推荐
- All about PDF crack, a complete solution to meet all your PDF needs
- opencv之图像分割
- iptables 之 state模块(ftp服务练习)
- Leetcode 1984. Minimum difference in student scores
- 調用華為遊戲多媒體服務的創建引擎接口返回錯誤碼1002,錯誤信息:the params is error
- 快速集成认证服务-HarmonyOS平台
- Required String parameter ‘XXX‘ is not present
- 下载和安装orcale database11.2.0.4
- MES system is a necessary choice for enterprise production
- Train your dataset with swinunet
猜你喜欢
opencv之图像分割
Exercise arrangement 2.10, 11
【MySQL】数据库进阶之触发器内容详解
Implementation of navigation bar at the bottom of applet
Data type - floating point (C language)
MySQL introduction - crud Foundation (establishment of the prototype of the idea of adding, deleting, changing and searching)
Coquette data completes the cloud native transformation through rainbow to realize offline continuous delivery to customers
[南京大学]-[软件分析]课程学习笔记(一)-introduction
国标GB28181协议视频平台EasyGBS新增拉流超时配置
调用华为游戏多媒体服务的创建引擎接口返回错误码1002,错误信息:the params is error
随机推荐
Open3d ISS key points
A single game with goods increased by 100000, and the rural anchor sold men's clothes on top of the list?
详解华为应用市场2022年逐步减少32位包体上架应用和策略
Go语言中,函数是一种类型
指针进阶,字符串函数
【MySQL】数据库进阶之触发器内容详解
2 - 3 arbre de recherche
Golan idea IntelliJ cannot input Chinese characters
A method for quickly viewing pod logs under frequent tests (grep awk xargs kuberctl)
The single value view in Splunk uses to replace numeric values with text
注解@ConfigurationProperties的三种使用场景
POJ - 3784 running medium
如何在快应用中实现滑动操作组件
联想混合云Lenovo xCloud:4大产品线+IT服务门户
Appeler l'interface du moteur de création du service multimédia de jeu Huawei renvoie le Code d'erreur 1002, le message d'erreur: les paramètres sont l'erreur
redis故障处理 “Can‘t save in background: fork: Cannot allocate memory“
[Yu Yue education] basic reference materials of electrical and electronic technology of Nanjing Institute of information technology
Le système mes est un choix nécessaire pour la production de l'entreprise
Through the "last mile" of legal services for the masses, fangzheng Puhua labor and personnel law self-service consulting service platform has been frequently "praised"
Interface as a parameter (interface callback)