QT的绘图系统QPainterDevice与文件系统QIODevice
QT的绘图系统(QPainterDevice)与文件系统(QIODevice)
文章目录
- 1、Qt 的绘图系统
- 1、QPainter的使用
- 2、QPen(画笔)及QBursh(画刷)
- 3、手动更新窗口
- 4、绘图设备
- 1、四种绘图设备的 区别
- 2、 QBitmap
- 3、QPixmap
- 4、 QImage
- 5、QPicture
- 6、QImage与QPixmap的转换
- 2、不规则窗口
- 3、文件系统
- 1、QFile文件的读写
- 2、QT的QString与QByteArray以及char *的相互转换
- 3、文件信息QFileInfo类
- 4、二进制文件读写 QDataStream类(打开是看不懂)
- 5、文本文件读写QTextStream类
- 6、内存读写QBuffer类
- 4、总结
1、Qt 的绘图系统
Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。
下图给出了这三个类之间的层次结构:
上面的示意图告诉我们,Qt 的绘图系统实际上是,使用QPainter在QPainterDevice上进行绘制,它们之间使用QPaintEngine进行通讯(也就是翻译QPainter的指令)。
1、QPainter的使用
对窗口绘图首先要重写**void paintEvent(QPaintEvent *)**虚函数。
- 重写绘图事件,虚函数
- 如果在窗口绘图,必须放在绘图事件里实现
- 绘图事件内部自动调用,窗口需要重绘的时候(状态改变)
void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);//指定当前窗口为绘图设备p.drawPixmap(rect(), QPixmap("../Image/bk.jpg")); //画背景图//画直线p.drawLine(50, 50, 150, 50); /* 在坐标50,50的位置画长150,宽50的线 */p.drawLine(50, 50, 50, 150);//画矩形;l;dp.drawRect(150, 150, 100, 50);//画圆形p.drawEllipse(QPoint(150, 150), 50, 25);
}
注意:在上层目录要有背景图的存在。要先画背景图在画直线,矩形,圆形。
指定QQidget对象为绘图对象。即窗口是绘图设备。QQidget继承与QPaintDevice.
2、QPen(画笔)及QBursh(画刷)
QPainter有很多以 draw 开头的函数,用于各种图形的绘制,比如drawLine(),drawRect()以及drawEllipse()等。
如果需要设置画家的颜色,风格,线条的粗细。从而引入画笔。如果需要填充图形的颜色需要画刷。
void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);//指定当前窗口为绘图设备//画背景图p.drawPixmap(rect(), QPixmap("../Image/bk.jpg"));//定义画笔QPen pen;pen.setWidth(5); //设置线宽pen.setColor( QColor(14, 9, 234) );//rgb设置颜色pen.setStyle(Qt::DashLine); //设置风格p.setPen(pen); //把画笔交给画家QBrush brush; //创建画刷对象brush.setColor(Qt::red); //设置颜色brush.setStyle(Qt::Dense1Pattern);//设置样式p.setBrush(brush);//把画刷交给画家//画直线p.drawLine(50, 50, 150, 50); /* 在坐标50,50的位置画长150,宽50的线 */p.drawLine(50, 50, 50, 150);//画矩形;l;dp.drawRect(200, 200, 100, 50);//画圆形p.drawEllipse(QPoint(150, 150), 50, 25);
}
3、手动更新窗口
当我们在窗口绘制的图不断变化时。需要不断地刷新窗口才会有变化。否则不会有。
mywidget.h
class MyWidget : public QWidget
{Q_OBJECT
public:MyWidget(QWidget *parent = nullptr);~MyWidget();void paintEvent(QPaintEvent *);
private:int x;QPushButton *button;
private slots:void FunSlot(void);
private:Ui::MyWidget *ui;
};
mywidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QPainter>MyWidget::MyWidget(QWidget *parent) :QWidget(parent),ui(new Ui::MyWidget)
{ui->setupUi(this);x = 0;QPushButton *button = new QPushButton(this);button->setText("向右移动");connect(button, &QPushButton::pressed, this, &MyWidget::FunSlot);
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);//画笑脸p.drawPixmap(x, 180, 80, 80, QPixmap("../Image/face.png"));}
void MyWidget::FunSlot(void)
{x += 20;if(x > width()- 80){x = 0;}//刷新窗口,让窗口重绘,整个窗口都刷新update(); //间接调用paintEvent()
}
点击按钮绘图不断向右移动变化。到窗口终点又回到起点。
4、绘图设备
1、四种绘图设备的 区别
绘图设备是指继承QPainterDevice的子类。Qt一共提供了四个这样的类,分别是QPixmap、QBitmap、QImage和 QPicture。
**QBitmap:**是QPixmap的一个子类,它的色深限定为1,可以使用 QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap。
总结:它们操作都方法都是差不多一样的。
2、 QBitmap
QBitmap只有黑白两种颜色。
void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);//QPixmap 图片背景透明p.drawPixmap(0, 0, QPixmap("../Image/face.png"));//QBitmap 图片背景透明p.drawPixmap(200, 0, QBitmap("../Image/face.png"));//QPixmap 图片背景白色QPixmap pixmap;pixmap.load("../Image/image.jpg");p.drawPixmap(0, 200, pixmap);//QBitmap 图片背景白色QBitmap bitmap;bitmap.load("../Image/image.jpg");p.drawPixmap(400, 200, bitmap);
}
右边为QBitmap 左边为QPixmap。上面的QBitmap为黑色背景。下面为QBitmap的白色背景。
3、QPixmap
如下在QPixmap绘图而不是在窗口。不用重写绘图事件。在构造函数里实现即可。
MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);//绘图设备, 400*300QPixmap pixmap(400, 300);QPainter p(&pixmap);//画笔填充白色背景色//p.fillRect(0, 0, 400, 300, QBrush(Qt::white));//画家填充白色背景色pixmap.fill(Qt::white);p.drawPixmap(0, 0, 80, 80, QPixmap("../Image/face.png"));//上层路径保存图片pixmap.save("../pixmap.jpg");
}
在上层目录生成pixmap.jpg文件。
4、 QImage
QImage可以对像素点进行操作。
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//创建一个绘图设备,QImage::Format_ARGB32背景是透明QImage image(400, 300, QImage::Format_ARGB32);QPainter p;p.begin(&image);//绘图p.drawImage(0, 0, QImage("../Image/image.jpg"));//对绘图设备前50个像素点进行操作for(int i = 0; i < 50; i++){for(int j = 0; j < 50; j++){image.setPixel(QPoint(i, j), qRgb(0, 255, 0)); /* 设置像素点 *///image.pixel(QPoint(i, j)); /* 获取像素点 */}}p.end();image.save("../image.png"); // 保存图片
}
在上层目录生成image.png文件。绿色部分为对像素点的操作。
5、QPicture
MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);QPicture picture;QPainter p;p.begin(&picture);p.drawPixmap(0, 0, 80, 80, QPixmap("../Image/face.png"));p.drawLine(50, 50, 150, 50);p.end();//保存的是二进制文件picture.save("../picture.png");
}
在上层路径生成picture.png的二进制文件。
二进制打开也看不出效果。我们在窗口里加载出来。重写绘图事件。
void MyWidget::paintEvent(QPaintEvent *)
{QPicture pic;pic.load("../picture.png"); //加载二进制picture.png文件QPainter p(this);p.drawPicture(0, 0, pic);
}
运行结果如下:
6、QImage与QPixmap的转换
在对屏幕进行优化可能需要用到QPixmap。在传输可能需要用到QImage。
void MyWidget::paintEvent(QPaintEvent *)
{QPainter p(this);QPixmap pixmap;pixmap.load("../Image/face.png");//QPixmap -> QImageQImage tempImage = pixmap.toImage();p.drawImage(0, 0, tempImage);QImage image;image.load("../Image/face.png");//QImage -> QPixmapQPixmap tempPixmap = QPixmap::fromImage(image);p.drawPixmap(200, 0, tempPixmap);
}
运行结果:
第一张是通过QPixmap转QImage画的。第二张是通过QImage转QPixmap画的。
2、不规则窗口
常见的窗体是各种方形的对话框,但有时候也需要非方形的窗体,如圆形,椭圆甚至是不规则形状的对话框。
widget.h
class Widget : public QWidget
{Q_OBJECT
public:explicit Widget(QWidget *parent = 0);~Widget();protected:void paintEvent(QPaintEvent *);void mouseMoveEvent(QMouseEvent *e);void mousePressEvent(QMouseEvent *e);
private:QPoint p;
private:Ui::Widget *ui;
};
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QMouseEvent>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//去窗口表框Qt::FramelessWindowHint windowFlags()其它属性不变setWindowFlags(Qt::FramelessWindowHint | windowFlags());//把窗口背景设置为透明setAttribute(Qt::WA_TranslucentBackground);
}Widget::~Widget()
{delete ui;
}void Widget::paintEvent(QPaintEvent *)
{QPainter p(this);p.drawPixmap(0, 0, QPixmap("../Image/sunny.png"));
}void Widget::mousePressEvent(QMouseEvent *e)
{if(e->button() == Qt::RightButton){//如果是右键close();}else if(e->button() == Qt::LeftButton){//求坐标差值//当前点击坐标(屏幕)-窗口左上角坐标p = e->globalPos() - this->frameGeometry().topLeft();}
}void Widget::mouseMoveEvent(QMouseEvent *e)
{/* 移动加鼠标左键按下 */if(e->buttons() & Qt::LeftButton){move(e->globalPos() - p); // 当前点击坐标(屏幕) - 求坐标差值}
}
当鼠标左键按下移动无规则窗口跟着移动。鼠标右键按下则无规则窗口关闭。
如下图片关于上面代码的坐标计算的示意图
3、文件系统
文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库,提供了跨平台的文件操作能力。Qt 通过QIODevice提供了对 I/O 设备的抽象,这些设备具有读写字节块的能力。下面是 I/O 设备的类图(Qt5):
1、QFile文件的读写
QFile提供了从文件中读取和写入数据的能力。
我们通常会将文件路径作为参数传给QFile的构造函数。不过也可以在创建好对象最后,使用setFileName()来修改。
ui界面如下:
功能:把读取到文件显示在文本框里。把文本框里的内容保存成文件。
#include "mywidget.h"
#include "ui_mywidget.h"
#include<QFile>
#include<QFileDialog>
#include<QDebug>MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);connect(ui->pushButtonRead, &QPushButton::pressed, this, &MyWidget::ReadSlot);connect(ui->pushButtonWrite, &QPushButton::pressed, this, &MyWidget::WriteSlot);
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::ReadSlot(void)
{QString path = QFileDialog::getOpenFileName(this,"open", "../", "TXT(*.txt)");if(path.isEmpty() == false){//文件对象QFile file(path);//打开文件,只读方式bool isOk = file.open(QIODevice::ReadOnly);if(isOk == true){
// 一次读取全部
#if 0 \//读文件,默认只识别utf8编码 在文件流才可以改变编码格式QByteArray array = file.readAll();//显示到编辑区//ui->textEdit->setText(QString(array));//ui->textEdit->setText(array);
#endif// 一次读取一行QByteArray array;while( file.atEnd() == false){//读一行array += file.readLine();}ui->textEdit->setText(array);}//关闭文件file.close();}
}void MyWidget::WriteSlot(void)
{QString path = QFileDialog::getSaveFileName(this, "save", "../", "TXT(*.txt)");if(path.isEmpty() == false){QFile file; //创建文件对象//关联文件名字file.setFileName(path);//打开文件,只写方式bool isOk = file.open(QIODevice::WriteOnly); /* 有就打开否则创建 */if(isOk == true){//获取编辑区内容QString str = ui->textEdit->toPlainText();//写文件file.write(str.toUtf8());}file.close();}
}
2、QT的QString与QByteArray以及char *的相互转换
// QString -> QByteArrayfile.write(str.toUtf8());//QString -> c++ string -> char *file.write(str.toStdString().data());//转换为本地平台编码file.write(str.toLocal8Bit());//QString -> QByteArrayQString buf = "123";QByteArray a = buf.toUtf8(); //中文a = buf.toLocal8Bit(); //本地编码//QByteArray -> char *char *b = a.data();//char * -> QStringchar *p = "abc";QString c = QString(p);
3、文件信息QFileInfo类
#include <QFileDialog>
#include <QFileInfo>
#include <QDebug>
#include <QDateTime>QString path = QFileDialog::getOpenFileName(this, "open", "../");if(path.isEmpty() == false){//获取文件信息QFileInfo info(path);qDebug() << "文件名字:" << info.fileName().toUtf8().data();qDebug() << "文件后缀:" << info.suffix();qDebug() << "文件大小:" << info.size();qDebug() << "文件创建时间:" <<info.birthTime().toString("yyyy-MM-dd hh:mm:ss"); //2024-01-04 15:13:00}
4、二进制文件读写 QDataStream类(打开是看不懂)
mywidget.h
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACEclass MyWidget : public QWidget
{Q_OBJECTpublic:MyWidget(QWidget *parent = nullptr);~MyWidget();void writeData();void readData();
private:Ui::MyWidget *ui;
};
mywidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDataStream>
#include <QFile>
#include <QDebug>
#define cout qDebug() << "[" << __FILE__ <<":" << __LINE__ << "]"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);writeData();readData();
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::writeData()
{//创建文件对象QFile file("../hello.txt");//打开文件, 只写方式打开bool isOk = file.open(QIODevice::WriteOnly);if(true == isOk){//创建数据流,和file文件关联//往数据流中写数据,相当于往文件里写数据QDataStream stream(&file);stream << QString("你好") << 777;file.close();}}void MyWidget::readData()
{//创建文件对象QFile file("../hello.txt");//打开文件, 只读方式打开bool isOk = file.open(QIODevice::ReadOnly);if(true == isOk){//创建数据流,和file文件关联//往数据流中读数据,相当于往文件里读数据QDataStream stream(&file);//读的时候,按写的顺序取数据QString str;int a;stream >> str >> a;//qDebug() << str.toUtf8().data() << a;cout << str.toUtf8().data() << a;file.close();}
}
先写入数据流(二进制形式),然后以写的顺序读出来。
需要注意的是,你必须按照写入的顺序,将数据读取出来。顺序颠倒的话,程序行为是不确定的,严重时会直接造成程序崩溃。
那么,既然QIODevice提供了read()、readLine()之类的函数,为什么还要有QDataStream呢?QDataStream同QIODevice有什么区别?区别在于,QDataStream提供流的形式,性能上一般比直接调用原始 API 更好一些。
5、文本文件读写QTextStream类
ui界面:
widget.h
#include <QWidget>namespace Ui {
class Widget;
}
class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();void writeData();
private slots:void on_pushButton_clicked();
private:Ui::Widget *ui;
};
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QTextStream>
#include <QFile>
#include <QDebug>
#include <QFileDialog>
#define cout qDebug() << "[" << __FILE__ <<":" << __LINE__ << "]"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);writeData();}Widget::~Widget()
{delete ui;
}void Widget::writeData()
{QFile file;file.setFileName("../TextStream.txt");bool isOk = file.open(QIODevice::WriteOnly);if(true == isOk){QTextStream stream(&file);//指定编码stream.setEncoding(QStringConverter::Utf8);stream << QString("你好") << 777;file.close();}
}void Widget::on_pushButton_clicked()
{QString path = QFileDialog::getOpenFileName(this,"open", "../" );if(false == path.isEmpty()){QFile file;file.setFileName(path);bool isOk = file.open(QIODevice::ReadOnly);if(true == isOk){QTextStream stream(&file);//指定编码stream.setEncoding(QStringConverter::Utf8);QString str = stream.readAll();ui->textEdit->setText(str);file.close();}}
}
当使用QDataStream写入的时候,实际上会在要写入的内容前面,额外添加一个这段内容的长度值。而以文本形式写入数据,是没有数据之间的分隔的。因此,使用文本文件时,很少会将其分割开来读取,而是使用诸如使用:
QTextStream::readLine() 读取一行
QTextStream::readAll()读取所有文本。
6、内存读写QBuffer类
QByteArray array;QBuffer memFile(&array); //创建内存文件 还指定QByteArray对象memFile.open(QIODevice::WriteOnly);memFile.write("5455454");memFile.write("6564565");memFile.close();qDebug() << memFile.buffer();qDebug() << "array:" << array;
写进了内存也保存在了指定的QByteArray对象里。
QBuffer与QDataStream一起操作dome。
QBuffer memFile1;memFile1.open(QIODevice::WriteOnly); /* 只写 */QDataStream stream(&memFile1); /* QBuffer与QDataStream关联 */stream << QString("测试") << 999;memFile1.close();/* 关闭文件 */qDebug() << memFile1.buffer();memFile1.open(QIODevice::ReadOnly); /* 只读 */QDataStream in;in.setDevice(&memFile1);QString str;int a;in >> str >> a;memFile1.close(); /* 关闭文件 */qDebug() << str.toUtf8().data() << a;qDebug() << memFile1.buffer();
运行结果:
4、总结
例如:以上就是今天要讲的内容,本文仅仅简单介绍了QT的绘图系统与文件系统。
相关文章:

QT的绘图系统QPainterDevice与文件系统QIODevice
QT的绘图系统(QPainterDevice)与文件系统(QIODevice) 文章目录 1、Qt 的绘图系统1、QPainter的使用2、QPen(画笔)及QBursh(画刷)3、手动更新窗口4、绘图设备1、四种绘图设备的 区别2、 QBitmap3…...

Spark流式读取文件数据
流式读取文件数据 from pyspark.sql import SparkSession ss SparkSession.builder.getOrCreate() # todo 注意1:流式读取目录下的文件 --》一定一定要是目录,不是具体的文件,# 目录下产生新文件会进行读取# todo 注意点2࿱…...
Leetcode 3011. Find if Array Can Be Sorted
Leetcode 3011. Find if Array Can Be Sorted 1. 解题思路2. 代码实现 题目链接:3011. Find if Array Can Be Sorted 1. 解题思路 这一题挺简单的,就是一个分组进行排序考察,我们将相邻且bit set相同的元素划归到同一组,然后进…...

Databend 开源周报第 129 期
Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展,遇到更贴近你心意的 Databend 。 支持标准流 标…...

python 正则表达式学习(1)
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。 1. 特殊符号 1.1 符号含义 模式描述^匹配字符串的开头$匹配字符串的末尾.匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包…...

安全防御-基础认知
目录 安全风险能见度不足: 常见的网络安全术语 : 常见安全风险 网络的基本攻击模式: 病毒分类: 病毒的特征: 常见病毒: 信息安全的五要素: 信息安全的五要素案例 网络空间:…...

各省税收收入、个人和企业所得税数据,Shp、excel格式,2000-2021年
基本信息. 数据名称: 各省税收收入、个人和企业所得税数据 数据格式: Shp、excel 数据时间: 2000-2021年 数据几何类型: 面 数据坐标系: WGS84 数据来源:网络公开数据 数据字段: 序号字段名称字段说明1sssr_2021税收收入(亿元&am…...

Vue记录
vue2、vue3记录,参考地址:尚硅谷Vue项目实战硅谷甄选,vue3项目TypeScript前端项目一套通关_哔哩哔哩_bilibili vue2记录 经典vue2结构 index.vue: <template><div>...</div> </template><script>…...

【JavaEE进阶】 Spring Boot⽇志
文章目录 🎋关于日志🚩为什么要学习⽇志🚩⽇志的⽤途🚩日志的简单使用 🎄打印⽇志🚩程序中得到⽇志对象🚩使⽤⽇志对象打印⽇志 🎍⽇志格式的说明🚩⽇志级别的作用&#…...

《GitHub Copilot 操作指南》课程介绍
第1节:GitHub Copilot 概述 一、什么是 GitHub Copilot 什么是 GitHub Copilot GitHub Copilot是GitHub与OpenAI合作开发的编程助手工具,利用机器学习模型生成代码建议。它集成在开发者的集成开发环境(IDE)中,可以根…...
结构体(C语言)
结构体 1.结构体基础知识: //结构是一些值的集合,这些值称为成员变量. // 结构的每个成员可以是不同类型的变量. 2.结构的定义 struct peo { char name[10];//姓名 char tele[12];//电话 char gender[5];//性别 int high;//身高 }; struct stu { struct…...

HNU-数据挖掘-实验1-实验平台及环境安装
数据挖掘课程实验实验1 实验平台及环境安装 计科210X 甘晴void 202108010XXX 文章目录 数据挖掘课程实验<br>实验1 实验平台及环境安装实验背景实验目标实验步骤1.安装虚拟机和Linux平台,熟悉Ubuntu环境。2.在Linux平台上搭建Python平台,并安装…...

JavaEE中的监听器的作用和工作原理
在JavaEE(Java Platform, Enterprise Edition)中,监听器(Listener)是一种重要的组件,用于监听和响应Web应用程序中的事件。监听器的作用是在特定的事件发生时执行一些自定义的逻辑。常见的监听器包括Servle…...
Webpack5入门到原理1:前言
为什么需要打包工具? 开发时,我们会使用框架(React、Vue),ES6 模块化语法,Less/Sass 等 css 预处理器等语法进行开发。 这样的代码要想在浏览器运行必须经过编译成浏览器能识别的 JS、Css 等语法…...

#vue3 实现前端下载excel文件模板功能
一、需求: 前端无需通过后端接口,即可实现模板下载功能。 通过构造一个 JSON 对象,使用前端常用的第三方库 xlsx,可以直接将该 JSON 对象转换成 Excel 文件,让用户下载模板 二、效果: 三、源码如下&…...

《WebKit 技术内幕》之五(3): HTML解释器和DOM 模型
3 DOM的事件机制 基于 WebKit 的浏览器事件处理过程:首先检测事件发生处的元素有无监听者,如果网页的相关节点注册了事件的监听者则浏览器会将事件派发给 WebKit 内核来处理。另外浏览器可能也需要处理这样的事件(浏览器对于有些事件必须响应…...

136基于matlab的自适应滤波算法的通信系统中微弱信号检测程序
基于matlab的自适应滤波算法的通信系统中微弱信号检测程序,周期信号加入随机噪声,进行滤波,输出滤波信号,程序已调通,可直接运行。 136 matlab自适应滤波算法LMS (xiaohongshu.com)...

【Linux】权限 !
Linux 权限 Liunx Linux 权限1 什么是权限1.1 Linux用户1.2 切换用户 2 权限管理2.1 文件访问者的分类2.2 文件类型和访问权限2.3 文件权限的设置方法chmod 命令chown 命令chgrp 命令umask 命令file 指令 2.4 目录权限粘滞位 3 权限总结 1 什么是权限 关于Linux的权限问题&…...
axios原理
文章目录 axios基本概念axios多种方式调用工具函数axios的拦截器如何实现?用的设计模式是哪种?axios如何实现取消请求,和cancelToken如何使用 axios基本概念 axios是目前比较流行的一个js库,是一个基于promise的网络数据请求库&am…...
epoll
常用函数 //创建 /** * param size 告诉内核监听的数目 * * returns 返回一个epoll句柄(即一个文件描述符) */ int epoll_create(int size);//控制 /** * param epfd 用epoll_create所创建的epoll句柄 * param op 表示对epoll监控描述符控制的动作 * * …...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...