QT实现带动态弹出动画的自定义通知提示框

            Qt中经常会用到提示框,用于交互操作!QMessageBox是被大多数人用到的,用起来是很方便,但是控件类型、大小、布局、样式、往往不是开发者想要的。本实例实现的Notification控件,是一种悬浮在角落的通知提醒框。

一、简述

         本文为大家分享了QT实现带动态弹出动画的自定义通知提示框的具体代码。在QT中实现带动态弹出动画的自定义通知提示框,可以使用QPropertyAnimation类来实现动画效果。

二、 设计思路        

        要实现一个带有动态弹出动画的自定义通知提示框,可以使用Qt的动画框架来实现。以下是本文介绍的实现方式:

  1. 创建一个自定义的通知提示框类。可以继承自QWidget,并在构造函数中设置窗口的初始大小和位置,以及其他相关的属性。

  2. 在通知提示框类中定义一个动画对象,例如QPropertyAnimation,用于控制弹出动画的效果。可以设置弹出动画的目标属性为窗口的位置或大小。

  3. 在通知提示框类中定义一个槽函数,用于处理通知提示框的关闭事件。可以在槽函数中使用动画对象来执行关闭动画,并在动画完成后关闭窗口。

  4. 在需要显示通知提示框的地方,创建通知提示框的实例,并调用其show()函数显示窗口。可以使用动画对象来执行弹出动画。

三、效果 

 

四、核心代码  
1、头文件
#ifndef NOTIFICATION_H
#define NOTIFICATION_H#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QTextEdit>
#include <QTimer>
#include <mutex>
#include <vector>//消息类型
enum NotifyType {Notify_Type_None = 0, // 普通Notify_Type_Success, // 成功Notify_Type_Error, // 错误Notify_Type_Warning, // 警告Notify_Type_Information // 信息
};//消息位置
enum NotifyPosition {Pos_Top_Right = 0, // 右上角开始提醒,从上至下Pos_Top_Left, // 左上角开始提醒,从上至下Pos_Bottom_Left, // 左下角开始提醒,从下至上Pos_Bottom_Right // 右下角开始提醒,从下至上
};class NotificationLabel;
class NotificationItem;
class Notification : public QObject
{Q_OBJECT
public:explicit Notification(QObject *parent = nullptr);~Notification() override;/*** @brief Push 显示提示框* @param type 提示类型* @param pos 提示的方向(左上、左下、右上、右下)* @param title 提示的标题* @param content 提示的内容* @param nLive 提示框的存活时间,默认3000ms,若该值等于0,提示框不消失。*/void Push(NotifyType type, NotifyPosition pos, QString title, QString content, int nLive = 3000);private:const int nMargin = 15;QSize m_size;std::mutex m_vecMtx;std::vector<NotificationItem*> m_vecItem;private slots:void itemRemoved(NotificationItem* pItem);
};class NotificationItem : public QWidget
{Q_OBJECT
public:explicit NotificationItem(QWidget* parent = nullptr,NotifyType type = Notify_Type_None,NotifyPosition pos = Pos_Top_Right,QString title = QString("标题"),QString content = QString("这是一个提示"),int nLife = 3000);~NotificationItem() override;void Show();NotifyPosition GetPosType() const;bool IsAppearEnd() const;private:void Appear();void Disappear();protected:void paintEvent(QPaintEvent *event) override;private:const int nFixedWidth = 300;const int nMinHeight = 50;const int nTopPadding = 14;const int nLeftPadding = 23;const int nRightPadding = 26;const int nMargin = 20;NotifyPosition m_enPos;QTimer m_liftTimer;int m_nLifeTime;bool m_bAppearEnd;signals:void itemRemoved(NotificationItem*);
};class NotificationLabel : public QWidget
{Q_OBJECT
public:explicit NotificationLabel(QWidget* parent = nullptr, int nFixedWidth = 300, QString content = "");~NotificationLabel() override;void Adjust();protected:void paintEvent(QPaintEvent *) override;private:QStringList m_strList;QString m_strText;int m_nHeight;int m_nMargin = 5; // 上下间距QColor m_conetentColor = QColor(0x606266); // 内容的字体颜色
};#endif // NOTIFICATION_H
2、实现代码
#include "notification.h"
#include <QPainter>
#include <QStyleOption>
#include <QGraphicsDropShadowEffect>
#include <QScrollBar>
#include <QPropertyAnimation>
#include <QApplication>
#include <QScreen>static int nAppearTime = 200; // 出现的时间200ms
static int nDisappearTime = 200; // 消失的时间200msNotification::Notification(QObject *parent) : QObject(parent)
{QWidget* pWidget = qobject_cast<QWidget*>(parent);if(pWidget == nullptr)throw std::runtime_error("parent of notification error!");m_size = pWidget->size();m_vecItem.reserve(30);
}Notification::~Notification()
{}void Notification::Push(NotifyType type, NotifyPosition pos, QString title, QString content, int nLive)
{std::lock_guard<std::mutex> lck(m_vecMtx);NotificationItem* pItem = new NotificationItem(qobject_cast<QWidget*>(parent()),type,pos,title,content,nLive);connect(pItem, &NotificationItem::itemRemoved, this, &Notification::itemRemoved);int currentHeight = 0;int currentX = 0;if(pos == NotifyPosition::Pos_Top_Right){currentX = m_size.width();currentHeight = nMargin;}else if(pos == NotifyPosition::Pos_Top_Left){currentX = -pItem->width();currentHeight = nMargin;}else if(pos == NotifyPosition::Pos_Bottom_Left){currentX = -pItem->width();currentHeight = m_size.height() - nMargin - pItem->height();}else{currentX = m_size.width();currentHeight = m_size.height() - nMargin - pItem->height();}for_each(m_vecItem.begin(), m_vecItem.end(), [&](NotificationItem* item) {if(item->GetPosType() == pos){if(pos == NotifyPosition::Pos_Top_Right){currentHeight += (item->height() + nMargin);}else if(pos == NotifyPosition::Pos_Top_Left){currentHeight += (item->height() + nMargin);}else if(pos == NotifyPosition::Pos_Bottom_Left){currentHeight -= (item->height() + nMargin);}else{currentHeight -= (item->height() + nMargin);}}});pItem->move(currentX, currentHeight);m_vecItem.emplace_back(pItem);pItem->Show();
}void Notification::itemRemoved(NotificationItem *pRemoved)
{std::unique_lock<std::mutex> lck(m_vecMtx);int currentY = 0;bool bFirst = true;NotifyPosition pos = pRemoved->GetPosType();for(auto itr = m_vecItem.begin(); itr != m_vecItem.end();){if(*itr == pRemoved){m_vecItem.erase(itr);break;}else ++itr;}for_each(m_vecItem.begin(), m_vecItem.end(), [&, pos, bFirst, currentY](NotificationItem* item) mutable {if(item->GetPosType() == pos){if(bFirst){if(pos == NotifyPosition::Pos_Top_Right){currentY = nMargin;}else if(pos == NotifyPosition::Pos_Top_Left){currentY = nMargin;}else if(pos == NotifyPosition::Pos_Bottom_Left){currentY = m_size.height() - nMargin - item->height();}else{currentY = m_size.height() - nMargin - item->height();}bFirst = false;}else{if(item->IsAppearEnd()){if(pos == NotifyPosition::Pos_Top_Right){currentY += (item->height() + nMargin);}else if(pos == NotifyPosition::Pos_Top_Left){currentY += (item->height() + nMargin);}else if(pos == NotifyPosition::Pos_Bottom_Left){currentY -= (item->height() + nMargin);}else{currentY -= (item->height() + nMargin);}}}if(item->IsAppearEnd()){QPropertyAnimation* pAnimation1 = new QPropertyAnimation(item, "geometry", this);pAnimation1->setDuration(nDisappearTime);pAnimation1->setStartValue(QRect(item->pos().x(),item->pos().y(),item->width(),item->height()));pAnimation1->setEndValue(QRect(item->pos().x(),currentY,item->width(),item->height()));pAnimation1->start(QAbstractAnimation::DeletionPolicy::DeleteWhenStopped);}}});
}///
NotificationItem::NotificationItem(QWidget *parent,NotifyType type,NotifyPosition pos,QString title,QString content,int nLife) : QWidget(parent),m_enPos(pos),m_bAppearEnd(false)
{setObjectName(QStringLiteral("notification_item"));QLabel* pTitle = new QLabel(title, this);pTitle->setObjectName(QStringLiteral("label_title"));NotificationLabel* pContent = new NotificationLabel(this, nFixedWidth - 10, content);QFont font;font.setPointSize(11);font.setFamily(QStringLiteral("Microsoft Yahei"));pContent->setFont(font);QPushButton* pClose = new QPushButton(this);pClose->setFixedSize(16, 16);pClose->setObjectName(QStringLiteral("btn_close"));pClose->setCursor(QCursor(Qt::PointingHandCursor));setStyleSheet(QStringLiteral("QWidget#notification_item{border:none;border-radius:8px;background-color:white;}""QLabel#label_title{border:none;background-color:white;font-family:Microsoft Yahei;font-size:20px;font-weight:700;color:#303133;}""QPushButton#btn_close{border:none;background-color:white;background-position:center;border-image:url(:/skin/notification_close.png);}""QPushButton:hover#btn_close{border-image:url(:/skin/notification_close_hover.png);}"));// 标题设置pTitle->setAlignment(Qt::AlignLeft | Qt::AlignTop);QFontMetrics fontWidth(pTitle->font());QString elideNote = fontWidth.elidedText(pTitle->text(),Qt::ElideRight,120);pTitle->setText(elideNote);pTitle->setToolTip(title);pTitle->adjustSize();// 内容设置pContent->Adjust();// 布局if(type != NotifyType::Notify_Type_None){QLabel* pIcon = new QLabel(this);pIcon->setStyleSheet(QStringLiteral("QLabel{border:none;background-color:white;}"));if(type == NotifyType::Notify_Type_Success){pIcon->setPixmap(QPixmap(":/skin/type_success.png"));}else if(type == NotifyType::Notify_Type_Error){pIcon->setPixmap(QPixmap(":/skin/type_error.png"));}else if(type == NotifyType::Notify_Type_Warning){pIcon->setPixmap(QPixmap(":/skin/type_warning.png"));}else{pIcon->setPixmap(QPixmap(":/skin/type_information.png"));}pIcon->adjustSize();setFixedSize(nFixedWidth + nLeftPadding + nRightPadding + pIcon->width() + 10,pContent->height() + pTitle->height() + 2 * nTopPadding + 5);pIcon->move(nLeftPadding, nTopPadding - std::abs(pIcon->height() - pTitle->height()) / 2);pTitle->move(pIcon->x() + pIcon->width() + 10, nTopPadding);}else{setFixedSize(nFixedWidth + nLeftPadding + nRightPadding,pContent->height() + pTitle->height() + 2 * nTopPadding + 5);pTitle->move(nLeftPadding, nTopPadding);}pContent->move(pTitle->x(), pTitle->y() + pTitle->height() + 5);pClose->move(width() - pClose->width() / 2 - nRightPadding, nTopPadding);QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect(this);effect->setBlurRadius(20);        // 阴影圆角的大小effect->setColor(Qt::gray);      //阴影的颜色effect->setOffset(0,0);          //阴影的偏移量setGraphicsEffect(effect);connect(pClose, &QPushButton::clicked, this, [&](){m_liftTimer.stop();Disappear();});connect(&m_liftTimer, &QTimer::timeout, this, [&](){m_liftTimer.stop();Disappear();});m_nLifeTime = nLife;hide();
}NotificationItem::~NotificationItem()
{}void NotificationItem::Show()
{show();Appear();
}NotifyPosition NotificationItem::GetPosType() const
{return m_enPos;
}bool NotificationItem::IsAppearEnd() const
{return m_bAppearEnd;
}void NotificationItem::Appear()
{QPropertyAnimation *animation = new QPropertyAnimation(this, "geometry");animation->setDuration(nAppearTime);animation->setStartValue(QRect(pos().x(), pos().y(), width(), height()));if(m_enPos == NotifyPosition::Pos_Top_Right){animation->setEndValue(QRect(pos().x() - width() - nMargin,pos().y(),width(),height()));}else if(m_enPos == NotifyPosition::Pos_Top_Left){animation->setEndValue(QRect(pos().x() + width() + nMargin,pos().y(),width(),height()));}else if(m_enPos == NotifyPosition::Pos_Bottom_Left){animation->setEndValue(QRect(pos().x() + width() + nMargin,pos().y(),width(),height()));}else{animation->setEndValue(QRect(pos().x() - width() - nMargin,pos().y(),width(),height()));}animation->start(QAbstractAnimation::DeletionPolicy::DeleteWhenStopped);connect(animation, &QPropertyAnimation::finished, this, [&](){m_bAppearEnd = true;if(m_nLifeTime > 0)m_liftTimer.start(m_nLifeTime);});
}void NotificationItem::Disappear()
{QGraphicsOpacityEffect *pOpacity = new QGraphicsOpacityEffect(this);pOpacity->setOpacity(1);setGraphicsEffect(pOpacity);QPropertyAnimation *pOpacityAnimation2 = new QPropertyAnimation(pOpacity, "opacity");pOpacityAnimation2->setDuration(nDisappearTime);pOpacityAnimation2->setStartValue(1);pOpacityAnimation2->setEndValue(0);pOpacityAnimation2->start(QAbstractAnimation::DeletionPolicy::DeleteWhenStopped);connect(pOpacityAnimation2, &QPropertyAnimation::finished, this, [&](){emit itemRemoved(this);deleteLater();});
}void NotificationItem::paintEvent(QPaintEvent *event)
{QStyleOption opt;opt.init(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);QWidget::paintEvent(event);
}//
NotificationLabel::NotificationLabel(QWidget *parent,int nFixedWidth,QString content) : QWidget(parent)
{setObjectName(QStringLiteral("motification_label"));setFixedWidth(nFixedWidth);m_strText = content;m_nHeight = 0;setStyleSheet(QStringLiteral("QWidget#motification_label{background-color:white;border:none;}"));
}NotificationLabel::~NotificationLabel()
{}void NotificationLabel::Adjust()
{m_strList.clear();QFontMetrics fm(font());int tpHeight = fm.height();int size = m_strText.length();QString strTp;for(int i = 0; i < size; i++){strTp.append(m_strText.at(i));int tpWidth = fm.horizontalAdvance(strTp);if(tpWidth > width()){i--;strTp.chop(1);m_strList.push_back(strTp);strTp.clear();m_nHeight += tpHeight;}else{if(i == size - 1){m_strList.push_back(strTp);strTp.clear();m_nHeight += tpHeight;}}}setFixedHeight(m_nHeight + tpHeight / 2);repaint();
}void NotificationLabel::paintEvent(QPaintEvent *event)
{QStyleOption opt;opt.init(this);QPainter p(this);p.setRenderHint(QPainter::Antialiasing);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);QFontMetrics fm(font());int tpHeight = fm.height();int height = tpHeight;p.setPen(m_conetentColor);for(int i = 0; i < m_strList.count(); i++){p.drawText(QPoint(0, height), m_strList[i]);height += (tpHeight + m_nMargin);}QWidget::paintEvent(event);
}

        以上是带动态弹出动画的自定义通知提示框实现代码,在实际使用中,可以根据需要进行扩展及自定义动画文件和样式。      

五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用此控件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "notification.h"Notification* nf = nullptr;MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);resize(500, 360);nf = new Notification(this);QPushButton* btn1 = new QPushButton("普通", this);QPushButton* btn2 = new QPushButton("成功", this);QPushButton* btn3 = new QPushButton("错误", this);QPushButton* btn4 = new QPushButton("警告", this);QPushButton* btn5 = new QPushButton("信息", this);connect(btn1, &QPushButton::clicked, this, [&](){nf->Push(NotifyType::Notify_Type_None,NotifyPosition::Pos_Top_Right,"标准提示","你好,世界!Hellow world!", 0);});connect(btn2, &QPushButton::clicked, this, [&](){nf->Push(NotifyType::Notify_Type_Success,NotifyPosition::Pos_Top_Left,"成功提示","你好,世界!Hellow world!");});connect(btn3, &QPushButton::clicked, this, [&](){nf->Push(NotifyType::Notify_Type_Error,NotifyPosition::Pos_Bottom_Left,"错误提示","你好,世界!Hellow world!");});connect(btn4, &QPushButton::clicked, this, [&](){nf->Push(NotifyType::Notify_Type_Warning,NotifyPosition::Pos_Bottom_Right,"警告提示","你好,世界!Hellow world!");});connect(btn5, &QPushButton::clicked, this, [&](){nf->Push(NotifyType::Notify_Type_Information,NotifyPosition::Pos_Top_Right,"信息提示","你好,世界!Hellow world!");});btn1->move(200, 50);btn2->move(200, 100);btn3->move(200, 150);btn4->move(200, 200);btn5->move(200, 250);
}MainWindow::~MainWindow()
{delete ui;
}

总结一下,QT实现带动态弹出动画的自定义通知提示框的实现步骤如下:

  1. 创建一个自定义的QWidget类作为提示框的界面。

  2. 在该QWidget类中添加需要显示的文字或图标等元素。

  3. 在QWidget类中添加动画效果,可以使用QPropertyAnimation类实现动画效果。可以使用这个类来实现提示框的弹出、缩放、渐变等效果。

  4. 在主窗口中使用QLayout来布局,并将该自定义QWidget类添加到主窗口中。

  5. 在需要显示提示框的地方,通过创建QWidget类的实例来显示提示框。可以通过调用QWidget类的show()方法来显示提示框。

  6. 可以设置定时器,在一定时间后隐藏提示框。可以使用QTimer类来实现定时器功能。可以通过调用QWidget类的hide()方法来隐藏提示框。

  7. 可以添加鼠标事件,例如鼠标点击提示框时隐藏提示框。可以通过重写QWidget类的鼠标事件来实现该功能。

 通过以上步骤,就可以实现带动态弹出动画的自定义通知提示框。可以根据需要自定义提示框的样式和动画效果,使其更加符合应用程序的需求。

        谢谢您的关注和阅读!如有任何问题或需要帮助,请随时与我联系。希望您能继续支持并享受更多精彩的内容。祝您生活愉快!

六、源代码下载

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

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

相关文章

Day07-ES集群加密,kibana的RBAC实战,zookeeper集群搭建,zookeeper基本管理及kafka单点部署实战

Day07-ES集群加密&#xff0c;kibana的RBAC实战&#xff0c;zookeeper集群搭建&#xff0c;zookeeper基本管理及kafka单点部署实战 0、昨日内容回顾:1、基于nginx的反向代理控制访问kibana2、配置ES集群TSL认证:3、配置kibana连接ES集群4、配置filebeat连接ES集群5、配置logsta…

Mysql-错误处理: Found option without preceding group in config file

1、问题描述 安装MYSQL时&#xff0c;在cmd中“初始化”数据库时&#xff0c;输入命令&#xff1a; mysqld --initialize --consolecmd报错&#xff1a; D:\mysql-5.7.36-winx64\bin>mysql --initialize --console mysql: [ERROR] Found option without preceding group …

打印室预约小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;附近打印店管理&#xff0c;文件打印管理&#xff0c;当前预约管理&#xff0c;预约历史管理&#xff0c;打印记录管理 开发系统&#xff1a;Windows 架构模式&#xff1a;SSM JD…

linux服务器如何创建Raid10阵列,删除raid10

文章目录 1&#xff0c;首先查看一下机器上有几块盘2&#xff0c;构建raid10阵列3&#xff0c;把制作好的 RAID 磁盘阵列格式化为 ext4 格式4&#xff0c;创建挂载点然后把硬盘设备进行挂载操作5&#xff0c;查看/dev/md0 磁盘阵列的详细信息6&#xff0c;删除raid10 1&#xf…

理解深度学习中的过拟合和Dropout

新书速览|PyTorch深度学习与企业级项目实战-CSDN博客 随着迭代次数的增加&#xff0c;我们可以发现测试数据的loss值和训练数据的loss值存在着巨大的差距&#xff0c; 如图4-8所示&#xff0c;随着迭代次数的增加&#xff0c;training loss越来越好&#xff0c;但test loss却越…

分布式缓存-Redis持久化

使用缓存的时候&#xff0c;我们经常需要对内存中的数据进行持久化&#xff08;将内存中的数据写入到硬盘中&#xff09;。 原因&#xff1a;重用数据&#xff08;比如重启机器、机器故障之后恢复数据&#xff09;&#xff0c;做数据同步&#xff08;比如 Redis 集群的主从节点…

广告投放的智能优化:Kompas.ai如何提高广告效果

在数字广告领域&#xff0c;智能优化已成为提升广告投放效果和投资回报率(ROI)的关键。Kompas.ai&#xff0c;一款先进的广告智能优化工具&#xff0c;利用数据分析和机器学习技术&#xff0c;帮助广告主实现更精准、高效的广告投放。 智能优化在提升广告效果中的作用 智能优化…

微调 Florence-2 - 微软的尖端视觉语言模型

Florence-2 是微软于 2024 年 6 月发布的一个基础视觉语言模型。该模型极具吸引力&#xff0c;因为它尺寸很小 (0.2B 及 0.7B) 且在各种计算机视觉和视觉语言任务上表现出色。 Florence 开箱即用支持多种类型的任务&#xff0c;包括: 看图说话、目标检测、OCR 等等。虽然覆盖面…

MySQL字符串魔法:拼接、截取、替换与定位的艺术

在数据的世界里&#xff0c;MySQL作为一把强大的数据处理利剑&#xff0c;其字符串处理功能犹如魔术师手中的魔法棒&#xff0c;让数据变换自如。今天&#xff0c;我们就来一场关于MySQL字符串拼接、截取、替换以及查找位置的奇幻之旅&#xff0c;揭开这些操作的神秘面纱。 介绍…

谷歌浏览器114之前、126、127、128版本驱动下载,实时更新

114之前版本下载链接在这里 126以后版本下载链接在此&#xff0c;只有后面status是绿色对勾的才可以下载&#xff0c;**驱动大版本一致就可以使用&#xff0c;不需版本号一模一样&#xff1b;**下载所需版本只需点击对应的版本名称即可跳转到对应版本的下载位置。 以正式版为例…

FullCalendar日历组件集成实战(20)

背景 有一些应用系统或应用功能&#xff0c;如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件&#xff0c;但功能比较简单&#xff0c;用来做数据展现勉强可用。但如果需要进行复杂的数据展示&#xff0c;以及互动操作如通过点击添加事件&#xff0…

C# modbus 图表

控件&#xff1a;chart1(图表)&#xff0c;cartesianChart1(第三方添加图表)&#xff0c;timer(时间) 添加第三方&#xff1a; 效果&#xff1a;图标会根据连接的温度&#xff0c;湿度用timer时间进行改变 Chart1控件样式&#xff1a;Series添加线条&#xff0c;颜色&#xf…

编程从零基础到进阶(更新中)

题目描述 依旧是输入三个整数&#xff0c;要求按照占8个字符的宽度&#xff0c;并且靠左对齐输出 输入格式 一行三个整数&#xff0c;空格分开 输出格式 输出它们按格式输出的效果&#xff0c;占一行 样例输入 123456789 -1 10 样例输出 123456789-1 10 #include "stdio.…

which 命令在Linux中是一个快速查找可执行文件位置的工具

文章目录 0、概念1、which --help2、which命令解释 0、概念 which命令用于查找命令的可执行文件的路径which 命令在 Linux 中用于查找可执行命令的完整路径。当你在 shell 中输入一个命令时&#xff0c;shell 会在环境变量 $PATH 定义的目录列表中查找这个命令。which 命令可以…

基于Python+Flask+SQLite的豆瓣电影可视化系统

FlaskMySQLEcharts 基于PythonFlaskSQLite的豆瓣电影可视化系统 Echarts 不支持登录注册&#xff0c;并且信息存储在数据库中 不含爬虫代码&#xff0c;或爬虫代码已失效 简介 基于PythonFlaskMySQL的豆瓣电影可视化系统&#xff0c;采用Echart构建图表&#xff0c;支持自定…

ARM架构与FreeRTOS中的内存管理(flash与SRAM,堆栈)

在ARM架构中&#xff0c;内存的地址空间是如何划分的&#xff0c;内存映射表是怎样的 在Cortex-M7中&#xff0c;存储器一共有4GB的地址空间&#xff0c;4GB的地址空间又被划分为8个区域块&#xff0c;每个块有512M的内存。 Note&#xff1a;4GB的地址空间为 0x0000 0000 - 0…

[C++] 深度剖析C_C++内存管理机制

文章目录 内存分布内存分布图解 C语言中动态内存管理方式malloc:callocrealloc C内存管理方式内置类型**自定义类型** operator new & operator deleteoperator new & operator delete函数operator newoperator delete **new T[N]** 与**delete[]** **定位new表达式(pl…

第二章 UI组件【Android基础学习】

第二章 UI组件【Android基础学习】 前言版权推荐开源第二章 UI组件2-1 布局管理器2-1-1 LinearLayout2-1-2 RelativeLayout 2-2 TextView2-3 Button2-4 EditText2-5 RadioButton2-6 复选框CheckBox2-7 ImageView2-8 列表视图 ListView2-9 网格视图 GridView2-10 滚动视图 Scrol…

深入理解Session和Cookie的作用与联系

深入理解Session和Cookie的作用与联系 1、什么是Cookie&#xff1f;1、什么是Session&#xff1f;1、Session和Cookie的联系4、实际应用场景 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Session和Cookie是两个至关重要的概念&#xff0c…

30.【C语言】详解printf

1.printf&#xff08;print formate&#xff09;输入函数 01.简单使用 调用前要引用头文件 #include <stdio.h> printf("abc"); 默认情况下打印完光标停留在同一行 \n可以换行 printf("abc\n"); ​ printf("ab\nc"); ​ printf(…