Qt 基于海康相机的视频绘图

需求

在视频窗口上进行绘图,包括圆,矩形,扇形等

效果

 思路:

自己取图然后转成QImage ,再向QWidget 进行渲染,根据以往的经验,无法达到很高的帧率。因此决定使用相机SDK自带的渲染功能,也就是传一个句柄给到sdk。但是这样视频渲染出来了,向上绘制图案,会被视频遮挡住,因此这里采用了两个窗口叠加,然后上层窗口设置透明背景的方式来实现。

底层取图窗口代码:

#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include <QWidget>
#include <windows.h>
#include <MvCameraControl.h>

#include "./util/PSEventController.h"
#include "graphwidget.h"
class CameraWidget : public QWidget
{
    Q_OBJECT
public:
    explicit CameraWidget(QWidget *parent = nullptr);
    ~CameraWidget();

    void updatePos(int x,int y);

private:
    bool findDevice();
    bool printDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo);
    void getImage();
    bool openDevice();
    bool closeDevice();

private:
    int nRet = MV_OK;
    void* handle = NULL;
    MV_CC_DEVICE_INFO_LIST stDeviceList = {0};
    std::atomic_bool bExit = true;
    HWND hwnd = NULL;

    GraphWidget * graphWidget=nullptr;
    QWidget *videoWidget =nullptr;

    std::atomic_bool isCapture{false};

private:
    void initData();
    void mvToQImage(MV_DISPLAY_FRAME_INFO &stDisplayInfo);

public slots:
    void on_psEvent_capture(bool isChecked);
    void on_psEvent_adjustImage(bool isChecked);
    void on_psEvent_fixImage(bool isChecked);

signals:
    void capture(QImage image);
};

#endif // CAMERAWIDGET_H


#include "camerawidget.h"

#include <iostream>
#include <mutex>
#include <thread>
#include <QWidget>
#include <QPainter>
#include <QGridLayout>
#include <QStackedLayout>
#include <QDebug>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>

CameraWidget::CameraWidget(QWidget *parent)
    : QWidget{parent}
{
    graphWidget = new GraphWidget(this);
    graphWidget->setWindowFlags(Qt::FramelessWindowHint|Qt::Dialog|Qt::WindowStaysOnTopHint|Qt::SubWindow);
    graphWidget->setAttribute(Qt::WA_TranslucentBackground, true);
    QPalette pal;
    pal.setColor(QPalette::Window,QColor(0,0,0,0));
    graphWidget->setAutoFillBackground(true);
    graphWidget->setPalette(pal);
    graphWidget->show();

    hwnd = (HWND)this->winId();
    openDevice();

    this->setFixedSize(816,683);
    graphWidget->setFixedSize(this->size());

    setUpdatesEnabled(false);
    setAttribute(Qt::WA_OpaquePaintEvent);

    initData();
}

CameraWidget::~CameraWidget()
{
    closeDevice();
}


bool CameraWidget::findDevice()
{
    //枚举设备
    nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
    if (MV_OK != nRet)
    {
        printf("Enum Devices fail! nRet [0x%x]\n", nRet);
        return false;
    }

    if (stDeviceList.nDeviceNum > 0)
    {
        for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++)
        {
            printf("[device %d]:\n", i);
            MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];
            if (NULL == pDeviceInfo)
            {
                break;
            }
            printDeviceInfo(pDeviceInfo);
        }
    }
    else
    {
        printf("Find No Devices!\n");
        return false;
    }
    return true;
}

bool CameraWidget::openDevice()
{
    if(!findDevice()){
        return false;
    }

    unsigned int nIndex = 0;
    if (nIndex >= stDeviceList.nDeviceNum)
    {
        printf("Invalid device index!\n");
        return false;
    }

    do
    {
        //选择设备并创建句柄
        nRet = MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nIndex]);
        if (MV_OK != nRet)
        {
            printf("Create Handle fail! nRet [0x%x]\n", nRet);
            break;
        }

        // ch:打开设备
        nRet = MV_CC_OpenDevice(handle);
        if (MV_OK != nRet)
        {
            printf("Open Device fail! nRet [0x%x]\n", nRet);
            break;
        }

        // ch:探测网络最佳包大小(只对GigE相机有效)
        if (stDeviceList.pDeviceInfo[nIndex]->nTLayerType == MV_GIGE_DEVICE)
        {
            int nPacketSize = MV_CC_GetOptimalPacketSize(handle);
            if (nPacketSize > 0)
            {
                nRet = MV_CC_SetIntValue(handle,"GevSCPSPacketSize",nPacketSize);
                if(nRet != MV_OK)
                {
                    printf("Warning: Set Packet Size fail nRet [0x%x]!", nRet);
                }
            }
            else
            {
                printf("Warning: Get Packet Size fail nRet [0x%x]!", nPacketSize);
            }
        }

        //设置触发模式为off
        nRet = MV_CC_SetEnumValue(handle, "TriggerMode", 0);
        if (MV_OK != nRet)
        {
            printf("Set Trigger Mode fail! nRet [0x%x]\n", nRet);
            break;
        }

        // ch:开始取流 | en:Start grab image
        nRet = MV_CC_StartGrabbing(handle);
        if (MV_OK != nRet)
        {
            printf("Start Grabbing fail! nRet [0x%x]\n", nRet);
            break;
        }
        bExit=false;

        std::thread t([&](){
            getImage();
        });
        t.detach();

        return true;
    }while (0);


    if (nRet != MV_OK)
    {
        if (handle != NULL)
        {
            MV_CC_DestroyHandle(handle);
            handle = NULL;
        }
    }

    return false;
}

bool CameraWidget::closeDevice()
{
    bExit=true;

    if (handle == NULL)
        return true;

    do{
        // ch:停止取流 | en:Stop grab image
        nRet = MV_CC_StopGrabbing(handle);
        if (MV_OK != nRet)
        {
            printf("Stop Grabbing fail! nRet [0x%x]\n", nRet);
            break;
        }

        // ch:关闭设备 | Close device
        nRet = MV_CC_CloseDevice(handle);
        if (MV_OK != nRet)
        {
            printf("ClosDevice fail! nRet [0x%x]\n", nRet);
            break;
        }

        // ch:销毁句柄 | Destroy handle
        nRet = MV_CC_DestroyHandle(handle);
        if (MV_OK != nRet)
        {
            printf("Destroy Handle fail! nRet [0x%x]\n", nRet);
            break;
        }

        handle = NULL;
        return true;
    }while (0);

    if (nRet != MV_OK)
    {
        if (handle != NULL)
        {
            MV_CC_DestroyHandle(handle);
            handle = NULL;
        }
    }

    return false;
}

void CameraWidget::initData()
{
    PSEventController::subscribe(this,"capture");
    PSEventController::subscribe(this,"adjustImage");
    PSEventController::subscribe(this,"fixImage");

    connect(this,&CameraWidget::capture,this,[&](QImage image){
       graphWidget->setBackgroundImage(QPixmap::fromImage(image),true);
    },Qt::UniqueConnection);
}

void CameraWidget::on_psEvent_capture(bool isChecked)
{
    if(!isChecked){
        QPixmap backgroundImage;
        graphWidget->setBackgroundImage(backgroundImage,false);
    }else{
        isCapture=true;
    }
}

void CameraWidget::on_psEvent_adjustImage(bool isChecked)
{
    graphWidget->setIsScale(true);
}

void CameraWidget::on_psEvent_fixImage(bool isChecked)
{
    graphWidget->setIsScale(false);
}

void CameraWidget::updatePos(int x, int y)
{
    graphWidget->move(x,y);
}

bool CameraWidget::printDeviceInfo(MV_CC_DEVICE_INFO *pstMVDevInfo)
{
    if (NULL == pstMVDevInfo)
    {
        printf("The Pointer of pstMVDevInfo is NULL!\n");
        return false;
    }
    if (pstMVDevInfo->nTLayerType == MV_GIGE_DEVICE)
    {
        int nIp1 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);
        int nIp2 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
        int nIp3 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
        int nIp4 = (pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);

        // ch:打印当前相机ip和用户自定义名字 | en:print current ip and user defined name
        printf("CurrentIp: %d.%d.%d.%d\n" , nIp1, nIp2, nIp3, nIp4);
        printf("UserDefinedName: %s\n\n" , pstMVDevInfo->SpecialInfo.stGigEInfo.chUserDefinedName);
    }
    else if (pstMVDevInfo->nTLayerType == MV_USB_DEVICE)
    {
        printf("UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName);
        printf("Serial Number: %s\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chSerialNumber);
        printf("Device Number: %d\n\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.nDeviceNumber);
    }
    else
    {
        printf("Not support.\n");
    }

    return true;
}

//std::once_flag flag;
void CameraWidget::getImage()
{
    int nRet = MV_OK;
    MV_FRAME_OUT stImageInfo = {0};
    MV_DISPLAY_FRAME_INFO stDisplayInfo = {0};

    while(1)
    {
        nRet = MV_CC_GetImageBuffer(handle, &stImageInfo, 1000);
        if (nRet == MV_OK)
        {
            // printf("Get Image Buffer: Width[%d], Height[%d], FrameNum[%d]\n",
            //  stImageInfo.stFrameInfo.nWidth, stImageInfo.stFrameInfo.nHeight, stImageInfo.stFrameInfo.nFrameNum);

            if (hwnd)
            {
                stDisplayInfo.hWnd = hwnd;
                stDisplayInfo.pData = stImageInfo.pBufAddr;
                stDisplayInfo.nDataLen = stImageInfo.stFrameInfo.nFrameLen;
                stDisplayInfo.nWidth = stImageInfo.stFrameInfo.nWidth;
                stDisplayInfo.nHeight = stImageInfo.stFrameInfo.nHeight;
                stDisplayInfo.enPixelType = stImageInfo.stFrameInfo.enPixelType;

                //转qt QImage 给到绘图窗口
                if(isCapture){
                    mvToQImage(stDisplayInfo);
                }


                //调整窗口尺寸
                //                std::call_once(flag, [&](){
                //                    int cW = stImageInfo.stFrameInfo.nWidth;
                //                    int cH = stImageInfo.stFrameInfo.nHeight;
                //                });

                MV_CC_DisplayOneFrame(handle, &stDisplayInfo);
            }

            nRet = MV_CC_FreeImageBuffer(handle, &stImageInfo);
            if(nRet != MV_OK)
            {
                printf("Free Image Buffer fail! nRet [0x%x]\n", nRet);
            }
        }
        else
        {
            printf("Get Image fail! nRet [0x%x]\n", nRet);
        }
        if(bExit)
        {
            break;
        }
    }
}

void CameraWidget::mvToQImage(MV_DISPLAY_FRAME_INFO &stDisplayInfo)
{
    QImage image;
    if(stDisplayInfo.enPixelType==PixelType_Gvsp_Mono8){
        image= QImage(stDisplayInfo.pData, stDisplayInfo.nWidth, stDisplayInfo.nHeight, QImage::Format_Indexed8);
    }else if(stDisplayInfo.enPixelType==PixelType_Gvsp_RGB8_Packed){
        image= QImage(stDisplayInfo.pData, stDisplayInfo.nWidth, stDisplayInfo.nHeight, QImage::Format_RGB888);
    }
    emit capture(image);
    isCapture=false;
}

上层绘图窗口代码:

#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include <QWidget>
#include <windows.h>
#include <MvCameraControl.h>

#include "./util/PSEventController.h"
#include "graphwidget.h"
class CameraWidget : public QWidget
{
    Q_OBJECT
public:
    explicit CameraWidget(QWidget *parent = nullptr);
    ~CameraWidget();

    void updatePos(int x,int y);

private:
    bool findDevice();
    bool printDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo);
    void getImage();
    bool openDevice();
    bool closeDevice();

private:
    int nRet = MV_OK;
    void* handle = NULL;
    MV_CC_DEVICE_INFO_LIST stDeviceList = {0};
    std::atomic_bool bExit = true;
    HWND hwnd = NULL;

    GraphWidget * graphWidget=nullptr;
    QWidget *videoWidget =nullptr;

    std::atomic_bool isCapture{false};

private:
    void initData();
    void mvToQImage(MV_DISPLAY_FRAME_INFO &stDisplayInfo);

public slots:
    void on_psEvent_capture(bool isChecked);
    void on_psEvent_adjustImage(bool isChecked);
    void on_psEvent_fixImage(bool isChecked);

signals:
    void capture(QImage image);
};

#endif // CAMERAWIDGET_H

#include "graphwidget.h"
#include <QGridLayout>
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>

#include "../graphics/bqgraphicsitem.h"

#define VIEW_CENTER viewport()->rect().center()
#define VIEW_WIDTH  viewport()->rect().width()
#define VIEW_HEIGHT viewport()->rect().height()

GraphWidget::GraphWidget(QWidget *parent)
    : QGraphicsView{parent}
{
    setAttribute(Qt::WA_TranslucentBackground);
    setStyleSheet("background: transparent;border:0px");
    setWindowFlags(Qt::FramelessWindowHint);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setRenderHint(QPainter::Antialiasing);
    scene = new QGraphicsScene(this);
    this->setScene(scene);
    setDragMode(ScrollHandDrag);
    this->setSceneRect(this->geometry());
    centerOn(0, 0);

    initData();
}

void GraphWidget::setIsScale(bool newIsScale)
{
    isScale = newIsScale;
    if(!isScale){
        revertSize();
    }
}

void GraphWidget::setBackgroundImage(const QPixmap &newBackgroundImage,bool newIsSetBackground)
{
    qDebug()<<"setBackgroundImage "<<newIsSetBackground;
    isSetBackground=newIsSetBackground;
    if(backgroundItem){
        scene->removeItem(backgroundItem);
        backgroundItem=nullptr;
    }

    if(isSetBackground){
        setAttribute(Qt::WA_TranslucentBackground,false);
        backgroundImage = newBackgroundImage;
        if(!backgroundImage.isNull()){
            backgroundItem = scene->addPixmap(backgroundImage);
            backgroundItem->setPos(-this->width()/2,-this->height()/2);
            backgroundItem->setZValue(-1000);

            backgroundItem->setFlags(QGraphicsItem::ItemIsSelectable |
                               QGraphicsItem::ItemIsMovable |
                               QGraphicsItem::ItemIsFocusable);
            update();
        }
    }else{
        setAttribute(Qt::WA_TranslucentBackground,true);
        revertSize();
    }

}

void GraphWidget::clearItem()
{
    for(int i=0;i<scene->items().size();i++){
        QGraphicsItem *item = scene->items().at(i);
        if(item->zValue()==-1000){
            continue;
        }else{
            scene->removeItem(scene->items().at(i));
        }
    }
}

void GraphWidget::on_psEvent_addLine(bool isChecked)
{
    clearItem();
    BRectangle *m_rectangle = new BRectangle(0, 0, 100, 50, BGraphicsItem::ItemType::Rectangle);
    scene->addItem(m_rectangle);
}

void GraphWidget::on_psEvent_addCircle(bool isChecked)
{
    clearItem();
    BConcentricCircle *m_conCircle = new BConcentricCircle(0, 0, 50, 80, BGraphicsItem::ItemType::Concentric_Circle);
    scene->addItem(m_conCircle);
}

void GraphWidget::on_psEvent_addEllipse(bool isChecked)
{
    clearItem();
    BEllipse *m_ellipse = new BEllipse(0, 0, 100, 50, BGraphicsItem::ItemType::Ellipse);
    scene->addItem(m_ellipse);
}

void GraphWidget::on_psEvent_addArc(bool isChecked)
{
    clearItem();
    BPie *m_pie = new BPie(0, 0, 80, 30, BGraphicsItem::ItemType::Pie);
    scene->addItem(m_pie);
}

void GraphWidget::wheelEvent(QWheelEvent *event)
{
    if(isScale){
        static float scale = 1.1;
        auto angle = event->angleDelta();

        if(angle.y() > 0)
        {
            this->scale(scale, scale);
        }
        else
        {
            this->scale(1/scale, 1/scale);
        }
    }
}

void GraphWidget::initData()
{
    PSEventController::subscribe(this,"addLine");
    PSEventController::subscribe(this,"addCircle");
    PSEventController::subscribe(this,"addEllipse");
    PSEventController::subscribe(this,"addArc");
}

void GraphWidget::revertSize()
{
    setTransformationAnchor(QGraphicsView::AnchorViewCenter);
    QMatrix q;
    q.setMatrix(1,this->matrix().m12(),this->matrix().m21(),1,this->matrix().dx(),this->matrix().dy());
    setMatrix(q,false);
}

主窗口移动和缩放时更新视频窗口位置:

void MainWindow::updateGraphWidgetPos()
{
    if(cameraWidget){
        QPoint p =  mapToGlobal(cameraWidget->parentWidget()->pos());
        cameraWidget->updatePos(p.x(),p.y()+22);
    }
}

void MainWindow::resizeEvent(QResizeEvent *e)
{
    updateGraphWidgetPos();
    return QWidget::resizeEvent(e);
}

void MainWindow::moveEvent(QMoveEvent *e)
{
    updateGraphWidgetPos();
    return QWidget::moveEvent(e);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DAY60 84.柱状图中最大的矩形

84.柱状图中最大的矩形 题目要求&#xff1a;给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 思路 单调栈 本地单调栈的解法和接雨水的题目是遥相呼…

【DevOps】Git 图文详解(七):标签管理

Git 图文详解&#xff08;七&#xff09;&#xff1a;标签管理 标签&#xff08;Tags&#xff09;指的是某个分支某个特定时间点的状态&#xff0c;是对某一个提交记录的 固定 “指针” 引用。一经创建&#xff0c;不可移动&#xff0c;存储在工作区根目录下 .git\refs\tags。可…

智能座舱架构与芯片- (4) 硬件篇 中

2.4 高速视频传输(GMSL) 为了解决未来汽车系统所面临的问题&#xff0c;美信(Maxim)推出了全新下一代GMSL技术&#xff0c;即吉比特多媒体串行链路(GMSL)串行器和解串器&#xff0c;用来支持未来ADAS和信息娱乐系统要求的宽带、互联复杂度和数据完整性的要求。 GMSL技术可以支…

Stock接口_节假日(1)

节假日 文章目录 节假日一. 查询最近十天的交易日日期列表二. 查询日期段内的交易日日期列表三. 查询假期信息 一. 查询最近十天的交易日日期列表 接口描述: 接口地址:/StockApi/holidayCalendar/getTenTradeDay 请求方式&#xff1a;GET consumes: produces:["*/*&q…

【C++】类和对象一

今天来到了类和对象部分&#xff0c;我们知道C语言是面向过程编程&#xff0c;而C是面向对象编程&#xff0c;那么怎么个具体实现方法呢&#xff1f;简单来说&#xff0c;就是C语言对结构体的定义和对结构体的操作是分开的&#xff0c;这样就显得过程很独立&#xff1b;而C是把…

Javaweb之Axios的详细解析

1.3 Axios 上述原生的Ajax请求的代码编写起来还是比较繁琐的&#xff0c;所以接下来我们学习一门更加简单的发送Ajax请求的技术Axios 。Axios是对原生的AJAX进行封装&#xff0c;简化书写。Axios官网是&#xff1a;https://www.axios-http.cn 1.3.1 Axios的基本使用 Axios的…

知识库文档处理

知识库文档处理 1 知识库设计2 文档加载2.1 PDF文档2.2 MD文档2.3 MP4视频 3 文档分割4 文档词向量化 本项目是一个个人知识库助手项目&#xff0c;旨在帮助用户根据个人知识库内容&#xff0c;回答用户问题。个人知识库应当能够支持各种类型的数据&#xff0c;支持用户便捷地导…

【Java程序员面试专栏 专业技能篇】Java SE核心面试指引(二):面向对象思想

关于Java SE部分的核心知识进行一网打尽,包括四部分:基础知识考察、面向对象思想、核心机制策略、Java新特性,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 本篇Blog为第二部分:面向对象思想,子节点表示追问或同级提问 面向对象基…

【用unity实现100个游戏之16】Unity程序化生成随机2D地牢游戏3(附项目源码)

文章目录 先本文看看最终效果前言二叉空间分割算法房间优先生成使用走廊连接各个房间BSP和随机游走源码完结 先本文看看最终效果 前言 前两期我们使用了随机游走算法已经实现了地牢的生成&#xff0c;本期再说另外一种生成地牢的方法&#xff0c;使用二叉空间分割算法&#xf…

Git——分布式版本控制工具

一、概述 1.开发中的实际场景 备份代码还原协同开发追溯问题代码的编写人和编写时间 2.版本控制器的方式 集中式版本控制工具 集中式版本控制工具&#xff0c;版本库是集中存放在中央服务器的&#xff0c;team里每个人work时从中央服务器下载代码&#xff0c;是必须联网才能…

nodejs微信小程序 +python+PHP- 校园志愿者管理系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Go 语言中 For 循环:语法、使用方法和实例教程

for循环用于多次执行特定的代码块&#xff0c;每次都可以使用不同的值。每次循环执行都称为一次迭代。for循环可以包含最多三个语句&#xff1a; 语法 for 语句1; 语句2; 语句3 {// 每次迭代要执行的代码 }语句1&#xff1a;初始化循环计数器的值。语句2&#xff1a;对每次循环…

微信小程序如何使用scss,less

搜到很多都是先VSCode安装好…插件…。这都是很久之前的方法了&#xff0c;所以想写这篇文章 一、修改project.config.json配置文件 "setting": {"useCompilerPlugins": ["sass"]},二、然后就可以删除 .wxss 文件了&#xff0c;就用 .scss 文件…

腾讯极光盒子A4021增强版_线刷官方

1、用USB_Burning_Tool线刷提供的线刷包&#xff0c;所需资料地址在最后 1&#xff09;打开USB_Burning_Tool&#xff0c;选择资料里的A4021_line_flash_root.img&#xff08;文件夹最好没有中文字符和空格&#xff09;&#xff0c;然后点击【开始】。 2&#xff09;盒子准备好…

mac添加Chrome插件的方法

如果是.crx的插件 更改后缀crx为zip 后续步骤同下文.zip文件 如果是.zip的插件 使用终端进行解压 注意不要用解压工具解压&#xff0c;一定要用终端&#xff0c;命令行解压 // 进入到“插件名.zip”文件的目录下&#xff0c;输入下面命令&#xff1a; unzip 插件名.zip -…

LeetCode209.长度最小的子数组(滑动窗口法、暴力法)

LeetCode209.长度最小的子数组 1.问题描述2.解题思路3.代码4.知识点 1.问题描述 给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果…

阿里云优惠券如何领取(阿里云在哪领取优惠券)

阿里云优惠券是阿里云为了回馈广大用户而推出的一种优惠活动&#xff0c;可以帮助用户在购买阿里云产品和服务时享受一定的优惠&#xff0c;本文将为大家介绍如何领取阿里云优惠券。 1、通过阿里云官网活动页面领取 阿里云会不定期举办一些优惠活动&#xff0c;例如双十一、双…

C语言基本算法之选择排序

目录 概要&#xff1a; 代码如下 运行结果如下 概要&#xff1a; 它和冒泡排序一样&#xff0c;都是把数组元素按顺序排列&#xff0c;但是方法不同&#xff0c;冒泡排序是把较小值一个一个往后面移&#xff0c;选择排序则是直接找出最小值&#xff0c;可以这个说&#xff…

IDEA如何将本地项目推送到GitHub上?

大家好&#xff0c;我是G探险者。 IntelliJ IDEA 是一个强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它支持多种编程语言和工具。它也内置了对Git和GitHub的支持&#xff0c;让开发者可以轻松地将本地项目推送到GitHub上。以下是一个操作手册&#xff0c;描述了…

身为程序员哪一个瞬间让你最奔溃 ?

身为程序员&#xff0c;有时候最让我感到沮丧的瞬间之一是遇到难以追踪和解决的 Bug。这些 Bug 可能出现在我写的代码中&#xff0c;也可能是由于不可预测的外部因素引起的。其中一个让我最奔溃的瞬间是在一个大型项目中&#xff0c;我遇到了一个非常复杂的Bug&#xff0c;这个…