QT下使用QChart绘制曲线

news2024/9/24 19:13:31

目录

    • 头文件内容
    • 构造函数
    • AddSeries方法
    • UpdateSeries方法
    • AppendSeriesData方法
    • SetLegendVisiable
    • SetRubberBand
    • CPP内容
    • 测试函数

在这里插入图片描述

需要用到的头文件:

#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QtCharts/QValueAxis>
#include <QPoint>
#include <QtCharts/QLineSeries>
#include <QString>
#include <QGridLayout>
#include <QLegendMarker>

直白一点说明,QChart用来存放曲线坐标轴和曲线,QChartView用来存放QChart,QChartView是一个Widget,可以独立show或者和其他widget做布局。

QLineSeries是直线,上图可以算是一个折线图,Qt还有散点图、光滑的曲线图、条形图、饼状图等等。

QValueAxis是坐标轴。

头文件内容

/*!
 * \file curve_charts.h
 * \date 2023/11/18 23:08
 *
 * \author 
 * Contact:
 *
 * \brief 
 *
 * 基于Qt的曲线图
 *
 * \note
*/

#pragma once

#include <unordered_map>

#include <QWidget>
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QtCharts/QValueAxis>
#include <QPoint>
#include <QtCharts/QLineSeries>
#include <QString>
#include <QGridLayout>
#include <QLegendMarker>
#include <QScatterSeries>

#define		QString2StdString(x)	((x).toStdString())
#define		StdString2QString(x)	(QString::fromLocal8Bit(std::string(x).c_str()))

QT_CHARTS_USE_NAMESPACE

class CurveCharts : public QWidget
{
	Q_OBJECT

public:
	CurveCharts(QWidget *parent = nullptr);
	~CurveCharts();

	/*!
	 * @func:  void AddSeries(const std::string _series_name, QPen _series_pen);
	 * 
	 * @date:  2023/11/18
	 * 
	 * @author:叫牌
	 * 
	 * @brief: 添加一条曲线,如果已经有这条曲线名称添加失败
	 *
	 * @param _series_name: 曲线名称
	 * @param _series_pen:  曲线颜色
	 * 
	 * @return: true添加成功,false添加失败
	*/
	bool AddSeries(const std::string& _series_name, QPen _series_pen);

	/*!
	 * @func:  void UpdateSeries(const std::string _series_name, std::vector<QPoint> _charts_data);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 通过曲线名称更新曲线
	 *
	 * @param _series_name: 曲线名称
	 * @param _charts_data: 曲线数据
	 *
	 * @return: true更新成功,false更新失败
	*/
	bool UpdateSeries(const std::string& _series_name, std::vector<QPoint> _charts_data);

	/*!
	 * @func:  void AppendSeriesData(const std::string& _series_name, std::vector<QPoint> _chart_data);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 通过曲线名称追加曲线数据
	 *
	 * @param _series_name: 曲线名称
	 * @param _charts_data: 曲线数据
	 *
	 * @return: true更新成功,false更新失败
	*/
	bool AppendSeriesData(const std::string& _series_name, std::vector<QPoint> _chart_data);

	/*!
	 * @func:  void SetTitle(const std::string _title);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 设置曲线标题
	 *
	 * @param _title: 曲线标题
	 *
	 * @return: 无
	*/
	void SetTitle(const std::string& _title);

	/*!
	 * @func:  std::string GetTitle();
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 获取曲线标题
	 *
	 * @return: 曲线标题
	*/
	std::string GetTitle();

	/*!
	 * @func:  void SetXAxisRange(qreal _x_min, qreal _x_max);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 设置X轴范围
	 *
	 * @return: 无
	*/
	void SetXAxisRange(qreal _x_min, qreal _x_max);

	/*!
	 * @func:  void SetYAxisRange(qreal _y_min, qreal _y_max);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 设置Y轴范围
	 *
	 * @return: 无
	*/
	void SetYAxisRange(qreal _y_min, qreal _y_max);

	/*!
	 * @func:  void SetTitle(const std::string& _XTitle, const std::string& _YTitle);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 设置Y轴范围
	 * 
	 * @param _XTitle: X坐标轴标题
	 * @param _YTitle: Y坐标轴标题
	 *
	 * @return: 无
	*/
	void setAxisTitles(const std::string& _XTitle, const std::string& _YTitle);

	/*!
	 * @func:  void SetAxisRanges(bool _flag);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 设置坐标轴自适应
	 *
	 * @param _flag: true表示自适应,false表示不自适应
	 *
	 * @return: 无
	*/
	void SetAxisRanges(const bool& _flag);

	/*!
	 * @func:  void SetLegendVisiable(const bool& _flag);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 设置图例显隐
	 *
	 * @param _flag: true表示显示,false表示隐藏
	 *
	 * @return: 无
	*/
	void SetLegendVisiable(const bool& _flag);

	/*!
	 * @func:  void SetRubberBand(const bool& _hor, const bool& _ver);
	 *
	 * @date:  2023/11/18
	 *
	 * @author:叫牌
	 *
	 * @brief: 设置垂直或水平缩放
	 *
	 * @param _hor: true表示打开水平缩放,false表示关闭
	 * @param _ver: true表示打开垂直缩放,false表示关闭
	 *
	 * @return: 无
	 * 
	 * @note: 垂直和水平缩放只能打开一个,都打开默认选择水平缩放
	*/
	void SetRubberBand(const bool& _hor, const bool& _ver);

private:

	QChartView* chart_view_;

	QChart* chart_;
	
	// X轴范围
	QValueAxis* x_axis_;
	// Y轴范围
	QValueAxis* y_axis_;

	// 存放所有的曲线
	// <曲线名称,对应的曲线指针>
	std::unordered_map<std::string, QLineSeries*> charts_series_;

	// 曲线数据的X和Y最小值
	QPoint axis_min_;
	// 曲线数据的X和Y轴最大值
	QPoint axis_max_;

	// 坐标轴是否自适应
	bool is_adaption_;

	// 图例是否显隐
	bool is_legend_;
};

我封装了接口供外部直接调用。

构造函数

CurveCharts::CurveCharts(QWidget* parent)
	: QWidget(parent)
	, chart_view_(new QChartView)
	, chart_(new QChart)
	, x_axis_(new QValueAxis)
	, y_axis_(new QValueAxis)
	, is_adaption_(false)
	, is_legend_(false)
{
	// 布局,栅格布局,把QChartView对象之间放进去,在main函数实例化对象调用show方法。
	QGridLayout* layout = new QGridLayout;
	this->setLayout(layout);
	layout->addWidget(chart_view_);

	// 窗口标题
	setWindowTitle(StdString2QString("曲线视图"));
	// 设置QChart
	chart_view_->setChart(chart_);
	// 设置X和Y坐标轴标题的显示位置,X轴标题在最小面,Y轴标题在左侧
	chart_->addAxis(x_axis_, Qt::AlignBottom);
	chart_->addAxis(y_axis_, Qt::AlignLeft);
	// 用于平滑图形的边缘和曲线,减少锯齿状的边缘
	chart_view_->setRenderHint(QPainter::Antialiasing);

	// 初始化最小最大值,方便记录X轴和Y轴所有曲线数据的最大最小值
	axis_min_.setX(INT_MAX);
	axis_min_.setY(INT_MAX);
	axis_max_.setX(INT_MIN);
	axis_max_.setY(INT_MIN);
}

构造函数里对各种成员变量初始化,进行布局,将QChartView对象通过栅格布局,设置X和Y轴的标题。

AddSeries方法

bool CurveCharts::AddSeries(const std::string& _series_name, QPen _series_pen)
{
	// 如果找到了就说明这个曲线的名称已经添加过了,不能重复添加或者覆盖
	if (charts_series_.find(_series_name) != charts_series_.end())
		return false;

	// 定义一个折线对象
	QLineSeries* line_series = new QLineSeries;
	charts_series_[_series_name] = line_series;

	// 添加到QChart
	chart_->addSeries(line_series);

	// 给这条折线添加颜色
	line_series->setPen(_series_pen);
	// 设置X轴
	line_series->attachAxis(x_axis_);
	// 设置Y轴
	line_series->attachAxis(y_axis_);
	// 设置这条折线的名字
	line_series->setName(StdString2QString(_series_name));

	// 为true表示显示图例
	if(is_legend_)
		chart_->legend()->markers(line_series)[0]->setLabel(StdString2QString(_series_name));

	return true;
}

这是一个添加曲线的函数,我们通过实例化该类的对象调用,参数就是你要添加曲线的名字,还有你想要它是什么颜色。

图例:
在这里插入图片描述

UpdateSeries方法

bool CurveCharts::UpdateSeries(const std::string& _series_name, std::vector<QPoint> _charts_data)
{
	// 找不到说明没有这条曲线
	if (charts_series_.find(_series_name) == charts_series_.end())
		return false;
	
	// 这是更新,所以得把之前这条曲线的数据清空
	charts_series_[_series_name]->clear();

	// 添加曲线数据,同时将最大最小值替换
	for (const auto& point : _charts_data)
	{
		qreal y_min = point.y() < axis_min_.y() ? point.y() : axis_min_.y();
		qreal y_max = point.y() > axis_max_.y() ? point.y() : axis_max_.y();

		qreal x_min = point.x() < axis_min_.x() ? point.x() : axis_min_.x();
		qreal x_max = point.x() > axis_max_.x() ? point.x() : axis_max_.x();

		axis_min_.setX(x_min);
		axis_min_.setY(y_min);
		axis_max_.setX(x_max);
		axis_max_.setY(y_max);

		charts_series_[_series_name]->append(point.x(), point.y());
	}

	// 如果是坐标轴自适应数据,那就通过设置坐标轴范围进行设置
	if (is_adaption_)
	{
		SetXAxisRange(axis_min_.x(), axis_max_.x());
		SetYAxisRange(axis_min_.y(), axis_max_.y());
	}

	return true;
}

这是更新曲线数据,所谓更新就是把之前的清空,是新一份数据,参数是要更新的曲线名称和数据。

AppendSeriesData方法

bool CurveCharts::AppendSeriesData(const std::string& _series_name, std::vector<QPoint> _chart_data)
{
	if (charts_series_.find(_series_name) == charts_series_.end())
		return false;

	for (const auto& point : _chart_data)
	{
		qreal y_min = point.y() < axis_min_.y() ? point.y() : axis_min_.y();
		qreal y_max = point.y() > axis_max_.y() ? point.y() : axis_max_.y();

		qreal x_min = point.x() < axis_min_.x() ? point.x() : axis_min_.x();
		qreal x_max = point.x() > axis_max_.x() ? point.x() : axis_max_.x();

		axis_min_.setX(x_min);
		axis_min_.setY(y_min);
		axis_max_.setX(x_max);
		axis_max_.setY(y_max);

		charts_series_[_series_name]->append(point.x(), point.y());
	}

	if (is_adaption_)
	{
		SetXAxisRange(axis_min_.x(), axis_max_.x());
		SetYAxisRange(axis_min_.y(), axis_max_.y());
	}

	return true;
}

追加曲线数据,我们需要在外部给某条曲线数据追加时,和更新的区别在于更新需要清空,而追加不需要,沿用之前的数据。

SetLegendVisiable

void CurveCharts::SetLegendVisiable(const bool& _flag)
{
	is_legend_ = _flag;

	if (is_legend_)
	{
		for (auto it = charts_series_.begin(); it != charts_series_.end(); it++)
			chart_->legend()->markers(it->second)[0]->setLabel(StdString2QString(it->first));
	}
}

设置是否显示图例,true表示显示,false表示不显示

SetRubberBand

void CurveCharts::SetRubberBand(const bool& _hor, const bool& _ver)
{
	if (_hor)
		chart_view_->setRubberBand(QChartView::HorizontalRubberBand);
	else if (_ver)
		chart_view_->setRubberBand(QChartView::VerticalRubberBand);
}

设置垂直缩放和水平缩放,但是这两个只能生效一个,不能同时生效。

剩下的方法就很简单,不做说明,直接贴源码。

CPP内容

#include "curve_charts.h"

CurveCharts::CurveCharts(QWidget* parent)
	: QWidget(parent)
	, chart_view_(new QChartView)
	, chart_(new QChart)
	, x_axis_(new QValueAxis)
	, y_axis_(new QValueAxis)
	, is_adaption_(false)
	, is_legend_(false)
{
	// 布局,栅格布局,把QChartView对象之间放进去,在main函数实例化对象调用show方法。
	QGridLayout* layout = new QGridLayout;
	this->setLayout(layout);
	layout->addWidget(chart_view_);

	// 窗口标题
	setWindowTitle(StdString2QString("曲线视图"));
	// 设置QChart
	chart_view_->setChart(chart_);
	// 设置X和Y坐标轴标题的显示位置,X轴标题在最小面,Y轴标题在左侧
	chart_->addAxis(x_axis_, Qt::AlignBottom);
	chart_->addAxis(y_axis_, Qt::AlignLeft);

	chart_view_->setRenderHint(QPainter::Antialiasing);

	// 初始化最小最大值,方便记录X轴和Y轴所有曲线数据的最大最小值
	axis_min_.setX(INT_MAX);
	axis_min_.setY(INT_MAX);
	axis_max_.setX(INT_MIN);
	axis_max_.setY(INT_MIN);
}

CurveCharts::~CurveCharts()
{}

bool CurveCharts::AddSeries(const std::string& _series_name, QPen _series_pen)
{
	// 如果找到了就说明这个曲线的名称已经添加过了,不能重复添加或者覆盖
	if (charts_series_.find(_series_name) != charts_series_.end())
		return false;

	// 定义一个折线对象
	QLineSeries* line_series = new QLineSeries;
	charts_series_[_series_name] = line_series;

	// 添加到QChart
	chart_->addSeries(line_series);

	// 给这条折线添加颜色
	line_series->setPen(_series_pen);
	// 设置X轴
	line_series->attachAxis(x_axis_);
	// 设置Y轴
	line_series->attachAxis(y_axis_);
	// 设置这条折线的名字
	line_series->setName(StdString2QString(_series_name));

	// 为true表示显示图例
	if(is_legend_)
		chart_->legend()->markers(line_series)[0]->setLabel(StdString2QString(_series_name));

	return true;
}

bool CurveCharts::UpdateSeries(const std::string& _series_name, std::vector<QPoint> _charts_data)
{
	// 找不到说明没有这条曲线
	if (charts_series_.find(_series_name) == charts_series_.end())
		return false;
	
	// 这是更新,所以得把之前这条曲线的数据清空
	charts_series_[_series_name]->clear();

	// 添加曲线数据,同时将最大最小值替换
	for (const auto& point : _charts_data)
	{
		qreal y_min = point.y() < axis_min_.y() ? point.y() : axis_min_.y();
		qreal y_max = point.y() > axis_max_.y() ? point.y() : axis_max_.y();

		qreal x_min = point.x() < axis_min_.x() ? point.x() : axis_min_.x();
		qreal x_max = point.x() > axis_max_.x() ? point.x() : axis_max_.x();

		axis_min_.setX(x_min);
		axis_min_.setY(y_min);
		axis_max_.setX(x_max);
		axis_max_.setY(y_max);

		charts_series_[_series_name]->append(point.x(), point.y());
	}

	// 如果是坐标轴自适应数据,那就通过设置坐标轴范围进行设置
	if (is_adaption_)
	{
		SetXAxisRange(axis_min_.x(), axis_max_.x());
		SetYAxisRange(axis_min_.y(), axis_max_.y());
	}

	return true;
}

bool CurveCharts::AppendSeriesData(const std::string& _series_name, std::vector<QPoint> _chart_data)
{
	if (charts_series_.find(_series_name) == charts_series_.end())
		return false;

	for (const auto& point : _chart_data)
	{
		qreal y_min = point.y() < axis_min_.y() ? point.y() : axis_min_.y();
		qreal y_max = point.y() > axis_max_.y() ? point.y() : axis_max_.y();

		qreal x_min = point.x() < axis_min_.x() ? point.x() : axis_min_.x();
		qreal x_max = point.x() > axis_max_.x() ? point.x() : axis_max_.x();

		axis_min_.setX(x_min);
		axis_min_.setY(y_min);
		axis_max_.setX(x_max);
		axis_max_.setY(y_max);

		charts_series_[_series_name]->append(point.x(), point.y());
	}

	if (is_adaption_)
	{
		SetXAxisRange(axis_min_.x(), axis_max_.x());
		SetYAxisRange(axis_min_.y(), axis_max_.y());
	}

	return true;
}

void CurveCharts::SetTitle(const std::string& _title)
{
	chart_->setTitle(StdString2QString(_title));
}

std::string CurveCharts::GetTitle()
{
	return QString2StdString(chart_->title());
}

void CurveCharts::SetXAxisRange(qreal _x_min, qreal _x_max)
{
	x_axis_->setRange(_x_min, _x_max);
}

void CurveCharts::SetYAxisRange(qreal _y_min, qreal _y_max)
{
	y_axis_->setRange(_y_min, _y_max);
}

void CurveCharts::setAxisTitles(const std::string& _XTitle, const std::string& _YTitle)
{
	x_axis_->setTitleText(StdString2QString(_XTitle));
	y_axis_->setTitleText(StdString2QString(_YTitle));
}

void CurveCharts::SetRubberBand(const bool& _hor, const bool& _ver)
{
	if (_hor)
		chart_view_->setRubberBand(QChartView::HorizontalRubberBand);
	else if (_ver)
		chart_view_->setRubberBand(QChartView::VerticalRubberBand);
}

void CurveCharts::SetAxisRanges(const bool& _flag)
{
	is_adaption_ = _flag;
}

void CurveCharts::SetLegendVisiable(const bool& _flag)
{
	is_legend_ = _flag;

	if (is_legend_)
	{
		for (auto it = charts_series_.begin(); it != charts_series_.end(); it++)
			chart_->legend()->markers(it->second)[0]->setLabel(StdString2QString(it->first));
	}
}

测试函数

#include <QtWidgets/QApplication>
#include <QTimer>
#include <random>

#include "curve_charts.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    CurveCharts* cure_charts = new CurveCharts;

    cure_charts->SetTitle("信号曲线");

    cure_charts->AddSeries("时域", QPen(QColor(Qt::green)));
    cure_charts->AddSeries("频域", QPen(QColor(Qt::red)));
    cure_charts->SetAxisRanges(true);
    cure_charts->SetLegendVisiable(true);
    cure_charts->SetRubberBand(true, false);
	cure_charts->setAxisTitles("时间", "幅度");

	int x = 0;

	QTimer timer;
	timer.setInterval(1000); // 设置定时间隔
	QObject::connect(&timer, &QTimer::timeout, [&]() {
		std::random_device rd;  // 随机设备,用于产生随机数种子
		std::mt19937 gen(rd()); // 使用随机设备的随机数引擎

		std::uniform_int_distribution<int> dist(0, 100); // 定义随机数分布范围为 [0, 100]

		std::vector<QPoint> temp1;
		std::vector<QPoint> temp2;

		int randomNumber1 = dist(gen);
		int randomNumber2 = dist(gen);

		QPoint point;
		point.setX(x);
		point.setY(randomNumber1);

		temp1.emplace_back(point);

		point.setY(randomNumber2);
		temp2.emplace_back(point);

		cure_charts->AppendSeriesData("时域", temp1);
		cure_charts->AppendSeriesData("频域", temp2);

		x++;
	});

	timer.start();

    cure_charts->show();

    return a.exec();
}

在测试代码中,我们添加了两条曲线,定义了一个定时器,间隔为1秒,每次产生两个0~100的随机值代表两条曲线的Y值,X值是时间。

另外,QChart支持设置背景色、十字线之类的效果,可以自己div。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1228058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据安全 测试

测试1、用户 hive/1.common2.hadoop.fql.comLEXIN.COM 和 nn/1.common2.hadoop.fql.com 分别对 Hive 进行查询 &#xff08;1&#xff09;HDFS 配置 vim /usr/local/fqlhadoop/hadoop/conf/core-site.xml <property><name>hadoop.proxyuser.hive.hosts</name&g…

16. @PostConstruct注解和开关原理(验证码开关、IP开关)

1►PostConstruct注解 PostConstruct是java自带的注解&#xff0c;会在java项目启动的时候先执行下面的方法 2►开关原理&#xff08;验证码开关&#xff09; 我们的项目具有验证码功能&#xff0c;旧版不支持关闭&#xff0c;新版已经支持关闭了。 我们打开页面“参数管…

go-zero微服务的使用

一、入门案例 1、使用goland创建一个工程 2、新建一个user.proto syntax "proto3";package user; // 这个地方表示生成的go的包名叫user option go_package "./user";message UserInfoRequest {int64 userId 1; }message UserInfoResponse {int64 user…

2024年csdn最新最全的Postman接口测试: postman实现参数化

什么时候会用到参数化 比如&#xff1a;一个模块要用多组不同数据进行测试 验证业务的正确性 Login模块&#xff1a;正确的用户名&#xff0c;密码 成功&#xff1b;错误的用户名&#xff0c;正确的密码 失败 postman实现参数化 在实际的接口测试中&#xff0c;部分参数…

【机器学习】特征工程:特征选择、数据降维、PCA

各位同学好&#xff0c;今天我和大家分享一下python机器学习中的特征选择和数据降维。内容有&#xff1a; &#xff08;1&#xff09;过滤选择&#xff1b;&#xff08;2&#xff09;数据降维PCA&#xff1b;&#xff08;3&#xff09;sklearn实现 那我们开始吧。 一个数据集中…

第93步 深度学习图像分割:PSPNet建模

基于WIN10的64位系统演示 一、写在前面 本期&#xff0c;我们继续学习深度学习图像分割系列的另一个模型&#xff0c;PSPNet。 二、PSPNet简介 &#xff08;1&#xff09;金字塔池化模块 (Pyramid Pooling Module) PSPNet的核心是其金字塔池化模块&#xff0c;该模块能够捕…

2024年csdn最新最全面的fiddler教程【1】

Fiddler简介 Fiddler是比较好用的web代理调试工具之一&#xff0c;它能记录并检查所有客户端与服务端的HTTP/HTTPS请求&#xff0c;能够设置断点&#xff0c;篡改及伪造Request/Response的数据&#xff0c;修改hosts&#xff0c;限制网速&#xff0c;http请求性能统计&#xff…

ERR:Navicat连接Sql Server报错

错误信息&#xff1a;报错&#xff1a;未发现数据源名称并且未指定默认驱动程序。 原因&#xff1a;Navicat没有安装Sqlserver驱动。 解决方案&#xff1a;在Navicat安装目录下找到sqlncli_x64.msi安装即可。 一键安装即可。 Navicat链接SQL Server配置 - MarchXD - 博客园 …

【腾讯云 HAI域探秘】——即时职场生存指南小游戏以及【自行搭建Stable Diffusion图片AI绘制 | ChatGLM2-6B AI进行智能对话 | Pytorch2.0 AI框架视频处理】

利用HAI的ChatGLM2 6B做一个即时对话小游戏 ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本&#xff0c;在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础之上&#xff0c;ChatGLM2-6B 引入了更强大的性能、更长的上下文、更高效的推理&#xff0c;…

论文阅读——DiffusionDet

在目标检测上使用扩散模型 前向过程&#xff1a;真实框-->随机框 后向过程&#xff1a;随机框-->真实框 前向过程&#xff1a; 一般一张图片真实框的数目不同&#xff0c;填补到同一的N个框&#xff0c;填补方法可以是重复真实框&#xff0c;填补和图片大小一样的框&a…

Linux操作文件的底层系统调用

目录 1.概述 2.open的介绍 3.write 的介绍 4.read 5.close的介绍 6.文件描述符 1.概述 C语言操作文件的几个库函数:fopen,fread,fwrite,fclose; 系统调用:open,read,write,close; 系统调用方法实现在内核中;(陷入内核,切换到内核) 2.open的介绍 open重载:两个参数用于打…

SpringSecurity6 | 默认登录页

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…

Javaweb之Vue生命周期的详细解析

2.4 生命周期 vue的生命周期&#xff1a;指的是vue对象从创建到销毁的过程。vue的生命周期包含8个阶段&#xff1a;每触发一个生命周期事件&#xff0c;会自动执行一个生命周期方法&#xff0c;这些生命周期方法也被称为钩子方法。其完整的生命周期如下图所示&#xff1a; 状…

vue3项目安装eslint和prettier

【几乎最全/全网最长的 2 万 字】前端工程化完整流程&#xff1a;从头搭到尾&#xff08;vue3 vite qiankun docker tailwindcss iview......&#xff09;_前端工程化流程-CSDN博客 vue3tsvite项目中使用eslintprettierstylelinthusky指南 - 掘金 上面两篇文章相互结合操…

Flutter最新稳定版3.16 新特性介绍

Flutter 3.16 默认采用 Material 3 主题&#xff0c;Android 平台预览 Impeller&#xff0c;DevTools 扩展等等 Flutter在每个季度通常都会有个稳定版本的发布。在2023 Q4的更新中为大家带来的是Flutter 3.16。这个版本将 Material 3 设为新的默认主题&#xff0c;并为 Android…

C++之常用算法

C之常用算法 for_each transform #include<iostream> using namespace std; #include<vector> #include<algorithm>class Tranfor { public:int operator()(int var){return var;} };class MyPrint { public:void operator()(int var){cout << var&l…

Shell判断:流程控制—if(二)

一、多分支结构 1、语法&#xff1a; if 条件测试1 then 命令序列 elif 条件测试2 then 命令序列 elif 条件测试3 then 命令序列.... else 命令序列 fi 2、示例&am…

入股合作协议要不要写章程

公司章程&#xff0c;是注册公司的基本文件&#xff0c;也公司必备的规定公司组织及活动基本规则的书面文件&#xff0c;是公司成立的必不可少的基础&#xff0c;也是公司赖以生存的灵魂。那么&#xff0c;这次要和大家讨论的是有关于入股合作协议要不要写章程的问题了。 入股合…

【开发流程】持续集成、持续交付、持续部署

一、开发工作流程 假设把开发流程分为以下几个阶段&#xff1a; 编码 -> 构建 -> 集成 -> 测试 -> 交付 -> 部署 如上图所示&#xff0c;持续集成、持续交付、持续部署有着不同的软件自动交付周期。 二、持续集成、持续交付、持续部署 1、持续集成 持续集成…

【Java 进阶篇】JQuery 事件绑定:`on` 与 `off` 的奇妙舞曲

在前端开发的舞台上&#xff0c;用户与页面的互动是一场精彩的表演。而 JQuery&#xff0c;作为 JavaScript 的一种封装库&#xff0c;为这场表演提供了更为便捷和优雅的事件绑定方式。其中&#xff0c;on 和 off 两位主角&#xff0c;正是这场奇妙舞曲中的核心演员。在这篇博客…