项目:微服务即时通讯系统客户端(基于C++QT)]四,中间界面搭建和逻辑准备

news2024/12/25 2:13:43

四,中间界面搭建

前言:当项目越来越复杂的时候,或许画草图是非常好的选择

一,初始化中间窗口initMidWindow

void mainWidget::initMidWindow()
{
    //使用网格布局进行管理
    QGridLayout* layout =new QGridLayout();
    //距离上方 20px 的距离,另外三个方向都不要边距
    layout->setContentsMargins(0,20,0,0);
    layout->setHorizontalSpacing(0);
    layout->setVerticalSpacing(10);
    windowMid->setLayout(layout);

    searchEdit =new QLineEdit();
    searchEdit->setFixedHeight(40);
    searchEdit->setPlaceholderText("这查找哦(●ˇ∀ˇ●)!");
    searchEdit->setStyleSheet(
        "QLineEdit {"
        "   border: 2px solid rgb(237,190,135);"  // 边框颜色
        "   border-radius: 10px;"        // 圆角
        "   padding: 5px;"                // 内边距
        "   background-color: #F0F0F0;A"  // 背景色
        "   color: #333333;"              // 字体颜色
        "   font-size: 14px;"             // 字体大小
        "   text-align: center;"       // 使用样式表来居中
        "}"
        "QLineEdit:focus {"
        "   border: 2px solid rgb(239,109,15);"  // 聚焦时边框颜色
        "   background-color: #FFFFFF;"   // 聚焦时背景色
        "}"
        );

    addUserBtn =new QPushButton();
    addUserBtn->setFixedSize(40,40);
    addUserBtn->setIcon(QIcon(":/resource/image/cross.png"));
    addUserBtn->setStyleSheet(
        "QPushButton {"
        "   background-color: #F0F0F0;"  // 背景颜色
        "   color: white;"                // 字体颜色
        "   border: none;"                // 无边框
        "   border-radius: 20px;"          // 圆角
        "   padding: 8px 18px;"          // 内边距
        "   cursor: pointer;"              // 鼠标指针
        "}"
        "QPushButton:hover {"
        "   background-color: #FFFFFF;"  // 鼠标悬停时的背景颜色
        "}"
        "QPushButton:pressed {"
        "   background-color: #EDBA39;"   // 按下时的背景颜色
        "}"
        );
    //为了更灵活的控制边界,只针对搜索按钮这行,所以我们可以创建空白的widget填充到我们的布局管理器中
    QWidget* space1 = new  QWidget();
    space1->setFixedWidth(8);
    QWidget* space2 = new  QWidget();
    space2->setFixedWidth(8);
    QWidget* space3 = new  QWidget();
    space3->setFixedWidth(8);

    //统一进行管理布局
    layout->addWidget(space1,0,0);
    layout->addWidget(searchEdit,0,1);
    layout->addWidget(space2,0,2);
    layout->addWidget(addUserBtn,0,3);
    layout->addWidget(space3,0,4);

    SessionFriendArea* sessionFriendArea=new SessionFriendArea();

    layout->addWidget(sessionFriendArea,1,0,1,5);//后面的为占据一行,横跨五列


}
  1. 首先创造一个网格布局管理器的指针

  2. 设置布局管理器的各项属性

  3. 将windowMid的布局管理器设为layout

  4. 创建一个新的 QLineEdit 对象,作为搜索框架,并且初始化各项参数

然后关于QLineEdit,它是 Qt 中用于输入和编辑单行文本的类。

别忘了在mainWidget中加入成员属性。

image.png

5.创建添加用户的按钮,并初始化各项外观属性

6.为了保持设置的HorizontalSpacing为0,我们手动增加各种控件。

7.添加SessionFriendArea()并且包含头文件,现在我们的目标就转移到了SessionFriendArea

image.png

使用布局管理器统一进行管理,我们画图来显示这么一部分

a98959fa0f5b4670dcd8ebaa1116f7a.jpeg

二,来构建sessionFriendArea吧

1.先来头文件,我们的头文件要继承自QScrollArea

class SessionFriendArea : public QScrollArea
{
    //1.这是一个宏,允许该类使用Qt的信号和槽机制
    Q_OBJECT
public:
    explicit SessionFriendArea(QWidget *parent = nullptr);
    //3.清空该区域所有item
    void clear();
    //4.添加一个item到该区域中(这个后面会再次改动)
    void addItem(const QIcon& user, const QString& name, const QString& text);
private:
    //5.往container内部的layout后续添加元素,能够触发QScrollArea滚动元素
    QWidget* container;//高度会随着里面添加的元素动态增加的。
    //通常container会被设置一个布局,该布局会管理其中的子空间,
    //并且由于QWidget可以根据控件大小自动调整大小
    //并且这个类作为一个滚动区域,它会显示container的可视区域,如果内容超过,会自动增加滚动条
//6.定义信号(待添加,用于实现逻辑)
signals:
};

注释讲解的很清楚了,我们来补充一下Q_OBJECT

image.png

2.我们来写构造函数SessionFriendArea(QWidget *parent)

SessionFriendArea::SessionFriendArea(QWidget *parent)
    : QScrollArea{parent}
{
    //1.设置滚动开启,并设置滚动条样式
    this->setWidgetResizable(true);//开启滚动效果
    this->verticalScrollBar()->setStyleSheet(
        "QScrollBar:vertical {"
        "   background: #F0F0F0;"              // 背景颜色
        "   width: 2px;"                      // 滚动条宽度
        "   border: none;"                     // 无边框
        "   border-radius: 1px;"               // 圆角
        "}"
        "QScrollBar::handle:vertical {"
        "   background: #FFABAB;"              // 滚动条颜色
        "   border-radius: 7px;"               // 圆角
        "   min-height: 7px;"                 // 滚动条最小高度
        "}"
        "QScrollBar::handle:vertical:hover {"
        "   background: #FF6F61;"              // 鼠标悬停时的颜色
        "}"
        "QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {"
        "   background: none;"                 // 上下箭头的背景
        "   height: 0px;"
        "}"
        "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {"
        "   background: none;"                 // 上下空白区域的背景
        "}"
        );
    ;//垂直方向的滚动条
    //设置不可见的水平滚动条
    this->horizontalScrollBar()->setStyleSheet(
        "QScrollBar:horizontal {"
        "   background: transparent;"  // 背景透明
        "   height: 2px;"              // 仍然保持高度为0,隐藏它
        "}"
    );
    this->setStyleSheet("QWidget {border : none;}");

    //2.把widget创建出来
    container=new QWidget();
    container->setFixedWidth(230);
    this->setWidget(container);//告诉滚动区,和哪个QWidget配合,和这个宽度为230的区域

    //3.给这个container widget指定布局管理器,以便后续添加元素进去
    QVBoxLayout* layout=new QVBoxLayout();
    layout->setContentsMargins(0,0,0,0);
    layout->setSpacing(0);
    layout->setAlignment(Qt::AlignTop);

    container->setLayout(layout);

    //4.简单测试一下UI效果
    // for(int i=0;i<500;i++)
    // {
    //     QPushButton* btn =new QPushButton();
    //     btn->setText("测试");
    //     layout->addWidget(btn);
    // }
//4.测试工程展示ui效果
#if TEST_UI1
    QIcon icon(":/resource/image/defaultAvatar1.png");
    for(int i=0;i<50;i++)
    {
        this->addItem(icon,"正切"+QString::number(i),"最后一条消息"+QString::number(i));
    }
#endif
}

3.写clear函数

void SessionFriendArea::clear()
{
    //1.取出布局管理器
    QLayout* layout = container->layout();//遍历布局管理器中的所有元素,并依次从布局管理器中删除掉
    // for(int i=0;i<layout->count();++i){// takeAt 就能移除对应下标的元素
    //     layout->takeAt(i);
    // }
    //上面的是有问题的
    //2.遍历布局管理器的所有元素
    for(int i=layout->count()-1;i>=0;i--)
    {
        QLayoutItem* item=layout->takeAt(i);
        //从指定的布局(layout)中移除索引为 i 的布局项(QLayoutItem),并将其返回给item
        if(item->widget())
        {
            delete item->widget();
            //移除的item是否有关联的widget,如果有删除widget,释放空间
        }
    }
}

知识一:QLayoutItem*这是一个指向 QLayoutItem 类型的指针,表示布局中的一个项目

知识二:takeAt(i) 是 QLayout 类的成员函数,它接受一个整数参数 i,表示要移除的项目的索引。这个函数会从布局中移除该索引位置的项,并返回指向该项的指针。

知识三:item->widget() 方法返回与当前布局项关联的 QWidget 指针,这个if是在检查item种是否有关联的部件

4.添加sessionFriendArea的项目的函数

//添加一个item到该区域中
void SessionFriendArea::addItem(const QIcon& user, const QString& name, const QString& text)
{
    SessionFriendItem* item = new SessionFriendItem(this, user, name, text);
    container->layout()->addWidget(item);
}
//包含用户头像,名字,最后一段文本

f32ce6dee7f71c17efa600ca3f1af93.jpeg

三,增加一项又一项的item

1.头文件

class SessionFriendItem : public QWidget{
    Q_OBJECT;//加上这个宏
public:
    SessionFriendItem(QWidget* owner,const QIcon& user,const QString& name,const QString& text);

    //为了让QSS正常使用
    void paintEvent(QPaintEvent* event)override;
    //重写鼠标按压函数
    void mousePressEvent(QMouseEvent* event)override;
    //重写鼠标触但没压的函数
    void enterEvent(QEnterEvent* event)override;
    //重写移开鼠标的函数
    void leaveEvent(QEvent* event)override;

    void select();


private:
    //owner指向了上述的SessionFriendArea
    QWidget* owner;

    bool selected =false;
    //这个变量用来表示当前item是否是“选中”状态,实现后续选中效果


};

解释一下这里的owner

45e0c7367187a84df185373ce4ca9a1.jpeg

2.构造函数

SessionFriendItem::SessionFriendItem(QWidget* owner,const QIcon& user,const QString& name,const QString& text)
    :owner(owner)
{
    //1.设置样式
    this->setFixedHeight(70);//高度
    this->setStyleSheet("QWidget { background-color:rgb(70,70,70);}");
    //2.添加网格布局管理器
    QGridLayout* layout =new QGridLayout();
    layout->setContentsMargins(18,0,0,0);
    layout->setHorizontalSpacing(10);
    layout->setVerticalSpacing(0);
    this->setLayout(layout);

    //3.创建头像部件
    QPushButton* userbtn =new QPushButton();
    userbtn->setFixedSize(60,60);
    userbtn->setIconSize(QSize(60,60));
    userbtn->setIcon(user);
    userbtn->setStyleSheet("QPushButton {border:none;}");
    userbtn->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);

    //4.创建名字部件
    QLabel* nameLabel =new QLabel();
    nameLabel->setText(name);
    nameLabel->setStyleSheet("QLabel {font-size: 20px; color: white; font-weight: 400;}");
    nameLabel->setFixedHeight(35);
    nameLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);\
    //水平方向拓展,竖直方向固定

    //5.创建消息预览的label
    QLabel* messageLabel =new QLabel();
    messageLabel->setText(text);
    messageLabel->setStyleSheet("QLabel {font-size: 15px; color: white; font-weight: 400;}");
    messageLabel->setFixedHeight(35);
    messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    //6.进行布局管理,头像处于 0,0 位置,占据 2行,占据 2列
    layout->addWidget(userbtn,0,0,2,2);
    layout->addWidget(nameLabel,0,2,1,1);// 名字处于 0,2 位置,占据 1行,占据 1列
    layout->addWidget( messageLabel,1,2,1,1);// 消息预览处于 1,2 位置,占据 1 行,占据 1 列layout->addwidget(messageLabel,1,2,1,1);
};

c17c7277b8b513b3f105669cec115ad.jpeg

会发现这样不能设置stylesheet,现在我们来进行处理

原因:在Qt种,如果是给QWidget的子类,通过QSS设置背景色默认是不生效的,除非加上官方代码上的特殊代码

方法:

image.png

image.png

image.png

我们重写一下这个函数

void SessionFriendItem::paintEvent(QPaintEvent* event)
{
    (void)event;
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget,&opt,&p,this);

}

3.设置各种效果

image.png

void SessionFriendItem::mousePressEvent(QMouseEvent* event)
{
    (void)event;
    select();
}
void SessionFriendItem::select()
{
    //鼠标点击时会触发这个函数
    //拿到所有的兄弟元素
    const QObjectList children =this->parentWidget()->children();
    for(QObject* child :children)
    {
        if(!child->isWidgetType())
        {
            //判定是否是Widget
            continue;
        }
        //是 widget,就把这里的child 强转成SessionFriendItem
        SessionFriendItem* item=dynamic_cast<SessionFriendItem*>(child);
        if(item->selected)
        {
            item->selected =false;
            item->setStyleSheet("QWidget { background-color: rgb(100,100,100);}");
            //还原背景色
        }
        //点击时修改背景色
        this->selected =true;
        this->setStyleSheet("QWidget { background-color: rgb(200,200,200);}");
    }

}
//浮动到上面的情况
void SessionFriendItem::enterEvent(QEnterEvent* event)
{
    (void)event;
    // 当前这个 item 是选中状态,则背景色不受到该逻辑影响
    if(this->selected)
    {
        return;
    }
    //设置一个更深的颜色
    this->setStyleSheet("QWidget { background-color: rgb(150,150,150);}");
}
//重写移开鼠标的函数
void SessionFriendItem::leaveEvent(QEvent* event)
{
    (void)event;
    // 当前这个 item 是选中状态,则背景色不受到该逻辑影响
    if(this->selected)
    {
        return;
    }
    // 还原背景色
    this->setStyleSheet("QWidget { background-color: rgb(70,70,70);}");
}

四,封装必要的逻辑

1.实现点击的逻辑

//click函数
void SessionFriendArea::clickItem(int index)
{
    if(index<0||index>=container->layout()->count())
    {
        LOG()<<"指定的元素超出坐标范围,index是"<<index;
        return;
    }
    QLayoutItem* layoutItem=container->layout()->itemAt(index);
    //itemAt(index): 这是 QLayout 类的成员函数,它接受一个整数参数 index,表示要获取的布局项的索引。该函数返回对应索引的 QLayoutItem 指针,如果索引超出范围,则返回 nullptr.
    if(layoutItem ==nullptr || layoutItem->widget()==nullptr)
    {
        LOG()<<"指定的元素不存在,index="<<index;
        return;
    }
    //选中状态
    SessionFriendItem* item = dynamic_cast<SessionFriendItem*>(layoutItem->widget());
    item->select();
}

2.会话item的实现

class SessionItem : public SessionFriendItem
{
    Q_OBJECT;
public:
    //owner,会话id,用户名字,用户头像,用户最后一条信息
    SessionItem(QWidget* owner, const QString& chatSessionId,const QIcon& user,const QString& name,const QString& lastMessage);
private:
    //当前会话的id
    QString chatSessionId;
};
//继承自父类SessionFriendItem
SessionItem::SessionItem(QWidget* owner, const QString& chatSessionId,const QIcon& user,const QString& name,const QString& lastMessage)
{

}

image.png

这个报错的含义是:

**SessionItem** 的构造函数需要显式地初始化基类 **SessionFriendItem**,因为它没有默认构造函数。你可以在 **SessionItem** 的构造函数初始化列表中调用 **SessionFriendItem** 的构造函数。

SessionItem::SessionItem(QWidget* owner, const QString& chatSessionId,const QIcon& user,const QString& name,const QString& lastMessage)
    :SessionFriendItem{owner,user,name,lastMessage},chatSessionId{chatSessionId}
{
    
}

3.好友item的实现

class FriendItem : public SessionFriendItem
{
    Q_OBJECT;
public:
    //owner,会话id,用户名字,用户头像,用户最后一条信息
    FriendItem(QWidget* owner, const QString& userId,const QIcon& user,const QString& name,const QString& Description);
private:
    //好友用户的id
    QString userId;
};
FriendItem::FriendItem(QWidget* owner, const QString& userId,const QIcon& user,const QString& name,const QString& Description)
    :SessionFriendItem{owner,user,name,Description},userId{userId}
{

}

4.好友申请item的实现

class ApplyItem : public SessionFriendItem
{
    Q_OBJECT;
public:
    //owner,会话id,用户名字,用户头像,用户最后一条信息
    ApplyItem(QWidget* owner, const QString& userId,const QIcon& user,const QString& name);
private:
    //申请用户的id
    QString userId;
};

因为这里不用text的构造所以我们对text直接传入空字符串

ApplyItem::ApplyItem(QWidget* owner, const QString& userId,const QIcon& user,const QString& name)
    :SessionFriendItem{owner,user,name,""},userId{userId}
{

}

5.基于此对additem进行改造

void SessionFriendArea::addItem(ItemType itemtype,const QString id,const QIcon& user, const QString& name, const QString& text)
{
    SessionFriendItem* item =nullptr;
    if(itemtype==SessionItemType)
    {
        item=new SessionItem(this,id,user, name, text);
    }
    else if(itemtype==FriendItemType)
    {
        item=new FriendItem(this,id,user, name, text);
    }
    else if(itemtype==ApplyItemType)
    {
        item=new ApplyItem(this,id,user, name);
    }
    else{
        LOG()<<"错误的item"<<itemtype;
        return ;
    }

    container->layout()->addWidget(item);
}

6.对applyitem界面的调整

//abc代码
ApplyItem::ApplyItem(QWidget* owner, const QString& userId,const QIcon& user,const QString& name)
    :SessionFriendItem{owner,user,name,""},userId{userId}
{
    //1.移除父类的messageLabel
    //将ApplyItem的布局管理器强转为QGridLayout
    QGridLayout* layout =dynamic_cast<QGridLayout*>(this->layout());
    layout->removeWidget(messageLabel);
    //释放内存,否则会内存泄露
    delete messageLabel;

    //2.创建两个按钮出来并且美化字体
    QPushButton* accepBtn =new QPushButton();
    accepBtn->setText("同意");
    accepBtn->setStyleSheet("QPushButton {font-size: 15px; color: white; font-weight: 400; font-family: 'SimSun'; }");
    QPushButton* rejectBtn =new QPushButton();
    rejectBtn->setText("拒绝");
    rejectBtn->setStyleSheet("QPushButton {font-size: 15px; color: white; font-weight: 400; font-family: 'SimSun'; }");

    //3.添加到布局管理器中
    layout->addWidget(accepBtn,1,2,1,1);
    layout->addWidget(rejectBtn,1,3,1,1);
}
  1. 强转为网格布局

  2. 删除掉messageLabel,会发现父类里messageLabel是构造函数的局部变量。

image.png

我们改成protected让这个成员能够被子类访问,要记得释放内存,否则会内存泄漏

c.创建两个按钮出来7bddfa1878c7c4f7d52f06806dd0257.jpeg

这是产生的页面效果

image.png

d.很丑我们就调整名字、消息所占的列,并且美化字体

90e19493bdc3d1f008b8217609fe310.jpeg

产生的效果

image.png

image.png

7.点击逻辑的准备工作

Sessionltem :点击之后,应该要在主界面右侧消息展示区,加载出对应的消息列表.

Friendltem:点击之后,要切换到会话列表,并且选中对应的会话.

Applyltem:点击之后,无事发生.主要逻辑是靠"同意""拒绝"按钮触发的.

在父类上加虚函数active()

在子类上加重写的active()

image.png

image.png

并且对鼠标按压的触发做出逻辑实现

void SessionFriendItem::select()
{
    //鼠标点击时会触发这个函数
    //拿到所有的兄弟元素
    const QObjectList children =this->parentWidget()->children();
    for(QObject* child :children)
    {
        if(!child->isWidgetType())
        {
            //判定是否是Widget
            //如果不是不用处理
            continue;
        }
        //是 widget,就把这里的child 强转成SessionFriendItem
        SessionFriendItem* item=dynamic_cast<SessionFriendItem*>(child);
        if(item->selected)
        {
            item->selected =false;
            item->setStyleSheet("QWidget { background-color: rgb(70,70,70);}");
            //还原背景色
        }
    }
    //点击时修改背景色
    this->selected =true;
    this->setStyleSheet("QWidget { background-color: rgb(200,200,200);}");
    //提供逻辑
    this->active();
}

告一段落:

image.png

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

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

相关文章

QT开发:深入掌握 QtGui 和 QtWidgets 窗口管理:QMainWindow、QDialog 和 QWidget 的高级应用

目录 引言 1. QMainWindow&#xff1a;高级窗口类 基本结构 菜单栏、工具栏和状态栏 菜单栏 工具栏 状态栏 中心部件和可停靠窗口 中心部件 可停靠窗口 示例代码与详解 2. QDialog&#xff1a;对话框窗口类 模态和非模态对话框 模态对话框 非模态对话框 自定义…

「Java开发指南」如何用MyEclipse为iPhone搭建Spring应用程序?

本教程将引导您完成在iPhone上使用的软件组件生成&#xff0c;这就产生了一个完全实现的可运行iPhone应用程序&#xff0c;可以立即用于验证和测试生成的iPhone组件。在本教程中&#xff0c;您将学习如何&#xff1a; 从数据库表搭建到现有项目部署应用程序 MyEclipse v2024.…

点云配准ICP算法笔记

参考&#xff1a;【PCL】—— 点云配准ICP(Iterative Closest Point)算法_icp点云配准-CSDN博客 点云配准 计算出两个点云簇之间的变换矩阵&#xff0c;从而计算出位姿等信息&#xff0c;学习点云配准的目的是想要计算相邻两帧物体的点云之间的变换位姿&#xff0c;从而得到物…

企业合规新动力:天锐股份助力等保制度落地实施

等保是指对网络&#xff08;含信息系统、数据&#xff09;实施分等级保护、分等级监管&#xff0c;对网络中使用的网络安全产品实行按等级管理&#xff0c;对网络中发生的安全事件分等级响应、处置。 【地址&#xff1a;点击了解天锐股份数据安全产品】 等保的必要性 频发的网…

选择国企eHR人事管理系统的时候,应该注意什么?

近年来&#xff0c;中国正步入高速发展的黄金时期&#xff0c;国有企业&#xff08;国企&#xff09;在追求效率和管理水平提升方面迈出了重要步伐。为了进一步实现数字化、流程化和科学化管理&#xff0c;越来越多的国企选择引进eHR&#xff08;电子人力资源管理&#xff09;系…

Java-IO模型

所谓I/O就是计算机内存与外部设备之间拷贝数据的过程。由于CPU访问内存的速度远远高于外部设备&#xff0c;因此CPU是先把外部设备的数据读到内存里&#xff0c;然后再进行处理。对于一个网络I/O通信过程&#xff0c;比如网络数据读取&#xff0c;会涉及两个对象&#xff0c;一…

VMware复制Ubuntu虚拟机后网卡失效的问题

为了在个人电脑上搭建集群&#xff0c;我使用了多台VMware虚拟机来模拟集群主机。之前虚拟机的操作系统是Redhat时&#xff0c;我复制虚拟机后网卡功能没有问题&#xff0c;但这次换成Ubuntu操作系统&#xff0c;我复制了虚拟机后同时启动这两台虚拟机&#xff0c;其中一台虚拟…

软件测试谣言二三事,认真你就输了

软件测试在近几年关注度日益升高,这得益于行业快速发展,以及很多公司和国际接轨后,对质量要求的增高。 在网上相关的讨论中,有许多观点并不符合我在这个行业的感知,针对一些观点,在这里结合我自己多年的从事经验,给大家辟辟谣。 谣言一:软件测试入门容易,会点点点就…

vue结合element-ui实现列表拖拽变化位置,点击拖动图标拖动整个列表元素,使用tsx格式编写

先来看下需要实现的效果 当鼠标放在左侧图标上时&#xff0c;可以拖动整个列表元素&#xff0c;调整顺序 思路介绍 使用draggable可以设置元素可拖动&#xff0c;然后分别设置三个事件处理函数&#xff0c;监听onDragstart、onDragover、onDragend三个事件 注意&#xff1a…

基于STM32的智能温度监控系统

目录 引言项目背景环境准备 硬件准备软件安装与配置系统设计 系统架构关键技术代码示例 传感器数据采集与处理温度监控与报警显示功能应用场景结论 1. 引言 温度监控系统在许多应用场景中具有重要作用&#xff0c;例如工业、农业以及家居生活。通过使用STM32微控制器、温度传…

Excel:常用函数

一、DAYS&#xff08;返回两个日期之间的天数&#xff09; 以下演示是在windows操作系统环境&#xff0c;office软件进行操作的 1.1 单元格设置日期格式 1.2 设置Days函数 公式&#xff1a;DAYS(C2,B2) 全部天数 二、SUM&#xff08;求和&#xff09; 公式&#xff1a;SUM(…

第二届两岸新经济产业发展研讨会闭幕,爱迪斯通董事长发表演讲

9月29日&#xff0c;第二届两岸新经济产业发展研讨会在福州高新区圆满落幕。此次研讨会由清华大学两岸发展研究院主办&#xff0c;福州市招商行动领导小组办公室、福州高新区承办&#xff0c;汇聚了两岸的专家学者及企业家代表近200人&#xff0c;共同探讨新质生产力的发展与两…

宠物医院微信小程序源码

文章目录 前言研究背景研究内容一、主要技术&#xff1f;二、项目内容1.整体介绍&#xff08;示范&#xff09;2.系统分析3.数据表信息4.运行截图5.部分代码介绍 总结 前言 随着当代社会科技的迅速发展&#xff0c;计算机网络时代正式拉来帷幕&#xff0c;它颠覆性的影响着社会…

【回眸】Tessy 单元测试软件使用指南(四)常见报错及解决方案与批量初始化的经验

前言 分析时Tessy的报错 1.fatal error: Tricore/Compilers/Compilers.h: No such file or directory 2.error: #error "Compiler unsupported" 3.warning: invalid suffix on literal;C11 requires a space between literal and string macro 4.error: unknown…

YOLOv7改进:Unified-loU,用于高品质目标检测的统一loU ,2024年8月最新IoU

💡💡💡现有IoU问题点:IoU (Intersection over Union)作为模型训练的关键,极大地显示了当前预测框与Ground Truth框之间的差异。后续研究者不断在IoU中加入更多的考虑因素,如中心距离、纵横比等。然而,仅仅提炼几何差异是有上限的;而且新的对价指数与借据本身存在潜在…

优化Mysql

目录 Mysql优化就四种&#xff1a;定位慢查询/sql执行计划/索引/Sql优化经验... 2 1Mysql如何定位慢查询&#xff1f;... 2 2Sql语句执行很慢&#xff0c;如何分析呢&#xff1f;... 3 2.1那这个SQL语句执行很慢,如何分析呢?. 3 3&#xff0e;了解过索引吗?(什么是索引)…

DC00018基于java swing+MySQL花卉信息管理系统

1、项目功能演示 DC00018基于java swingMySQL花卉信息管理系统java项目信息管理系统 2、项目功能描述 基于java swingMySQL花卉信息管理系统 系统包括用户信息管理以及花卉信息管理等功能。 3、项目运行截图 4、项目核心代码 4.1 日期格式化 package utils;import java.t…

C++ STL容器(四) —— vector底层剖析

这篇讲解vector&#xff0c;不说废话&#xff0c;直接开始&#xff01; 文章目录 原理UML类图代码实现构造函数插入元素删除元素清空容器析构函数赋值运算符 案例分析 原理 这里简单说一下 vector 的大致思想&#xff0c;动态数组&#xff0c;即它的长度会随着我们插入元素而产…

【YOLO目标检测二维码数据集】共3112张、已标注txt格式、有训练好的yolov5的模型

目录 说明图片示例 说明 数据集格式&#xff1a;YOLO格式 图片数量&#xff1a;3112 标注数量(txt文件个数)&#xff1a;3112 标注类别数&#xff1a;1 标注类别名称&#xff1a;qrcode 数据集下载&#xff1a;二维码数据集 图片示例 数据集图片&#xff1a; 数据集…

【开源免费】基于SpringBoot+Vue.JS微服务在线教育系统(JAVA毕业设计)

本文项目编号 T 060 &#xff0c;文末自助获取源码 \color{red}{T060&#xff0c;文末自助获取源码} T060&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…