基于Qt的app开发第八天

news2025/5/17 1:58:08

写在前面

笔者是一个大一下计科生,本学期的课程设计自命题完成一个督促学生自律的打卡软件,目前已经完成了待办和打卡部分功能,本篇要完成规划板块不需要存储就能实现的功能

需求分析

这一板块内容相比前两个板块还有一些特殊,因为它需要展示两张表,而且每个大规划中的任务数不确定

显式顺序分析:第一个界面视图展示一列列长期规划,然后这一个个规划块里边又有一个一个小任务,且标注完成状态;选中规划块的列点击修改会跳转到第二个界面,然后每个任务块算一行,选中对应行可以修改,点新建可以新加一行,然后跳转到第三个界面;点击新建也是跳转到第二个界面,然后后续就是一样的

实现思路

(1)难点分析

这个项目的难点在于对tableView的操作,tableView可以设置行选中和列选中。这个板块第一个界面设置列选中,第二个界面设置行选中。通过tableView的QstandardItModel的索引来插每行和每列,新增小任务就是在最后一行的上一行插入新任务块

(2)思路梳理

先把控件改成tableView,第一个界面不需要插表头,第二个界面要插表头。然后还是用QString型的QList数据类型来做中介变量,因为这次的时间和打卡板块是一样的,只需要String存储。

实现数据导入和打卡板块几乎是一致的,只需要关注行和列的索引

具体实现

(1)修改控件

修改控件如图,并修改命名

(2)初始化表格

初始化表格就仿照前两个板块即可,包含引用头文件、开模型。

//这个函数的作用是获取并初始化第一个界面的TableView控件
void Plan::GetPlanShowTableView()
{
    //获取界面中的表格对象
    QTableView *planShow = ui->planShowTableView;


    // 设置表格的点击模式为列单选
    ui->planShowTableView->setSelectionBehavior(QAbstractItemView::SelectColumns); // 选择整列
    ui->planShowTableView->setSelectionMode(QAbstractItemView::SingleSelection);   // 单选模式

    planShow->setModel(model_1);
}

//这个函数的作用是获取并初始化第二个界面的TableView控件
void Plan::GetPlanDecideTableView()
{
    //获取界面中的表格对象
    QTableView *planDecide = ui->planDecideTableView;

    //设置planDecideTableView的表头
    model_2->setColumnCount(4);
    model_2->setHorizontalHeaderLabels({"开始时间", "结束时间", "事项", "完成情况"});

    //设置表格的点击模式为行单选
    ui->planDecideTableView->setSelectionBehavior(QAbstractItemView::SelectRows);   // 选择整行
    ui->planDecideTableView->setSelectionMode(QAbstractItemView::SingleSelection);  // 单选模式

    planDecide->setModel(model_2);
}

声明变量和包含头文件不重复了,这里附上两个表格的初始化函数

注意要在构造函数中调用这两个函数,笔者刚才跑出来发现没有表格,仔细检查发现是因为构造函数没调用函数

(3)实现新建

这个板块的新建稍微有些复杂,其实也不是复杂,就是实现长度更长了一点,现在笔者来梳理一下传递顺序:

第三个界面里设置起始时间和结束时间,事项以及完成情况——>在第二个界面里的表格出现这么一行,然后在第二个界面可以输入自我评价——>在第一个界面里的表格里出现一列,这一列包含标题、任务块、自我评价。任务块就是第二个界面表格里的内容

由第三个界面传到第二个界面可以使用QString型的动态数组当中介变量,第二个界面传到第一个界面稍稍与前边的板块不同

笔者这里说明一下我的思路:先把标题传回第一个界面,再把自我评价传回第一个界面,然后每个任务块还是使用动态数组传递,每个任务块插入的基准是最后一行的上一行

下边再来分析一下函数实现的顺序:

按钮槽函数自然还是要分成修改和新建功能的if判断

新建功能因为没有原文本,所以直接无脑往回传就可以了。在第三个界面的应用按钮的槽函数里将文本框内容传到第二个界面里,在第二个界面的应用槽函数里将表格里的内容传到第一个界面里

做到第二个界面向第一个界面传递时笔者遇到了问题,因为任务块可能不只有一个,所以需要用一个循环遍历所有行。然后每一行都向第一个界面里传数据

还有另一个问题:因为两个界面里都有应用和修改按钮,笔者最开始觉得设置一个模式选择器就可以,逐步深入的过程中发现还是需要每个界面各一个模式选择器

 if(addOrRevise_1==1)
    {
        //这几行代码的作用是获取第二个界面输入框里的文本
        QString title=ui->nameInput->text();
        QString evalution=ui->evaluationInput->toPlainText();

        int col = model_1->columnCount();
        model_1->insertColumn(col);
        QStandardItem *item=new QStandardItem(title);
        model_1->setItem(0,col,item);
        item=new QStandardItem(evalution);
        model_1->setItem(1,col,item);

        int currentRow=0;
        //这个循环的作用是把表格里的内容全部放到第一个界面里
        while(currentRow<model_2->rowCount())
        {
            //这几行代码是向中介数组中导入表格数据
            QModelIndex index = model_2->index(currentRow, 0);
            QString startTime = index.data().toString();
            index=model_2->index(currentRow,1);
            QString endTime=index.data().toString();
            index=model_2->index(currentRow,2);
            QString event=index.data().toString();
            index=model_2->index(currentRow,3);
            QString isSuccess=index.data().toString();

            shiftPlanList.append(startTime);
            shiftPlanList.append(endTime);
            shiftPlanList.append(event);
            shiftPlanList.append(isSuccess);

            //这几行代码的作用是向planShowtableView里添加一个任务块
            int lastRow = 0;
            if (model_1->hasChildren())
            {
                // 从模型底部向上查找第一个有数据的单元格
                for (int i = model_1->rowCount() ; i >= 0; i--)
                {
                    if (!model_1->index(i, col).data().isNull())
                    {
                        lastRow = i; // 找到后,插入位置为这一行
                        break;
                    }
                }
            }
            for (int crow = lastRow,cindex=0; crow < lastRow+4; crow++,cindex++)
            {
                QStandardItem *item = new QStandardItem(shiftPlanList.at(cindex));
                model_1->setItem(crow, col, item);
            }
            QStandardItem *item = new QStandardItem(evalution);
            model_1->setItem(lastRow+4,col,item);

            shiftPlanList.clear();
            currentRow++;
        }

        //把这个索引置零,防止干扰后续操作
        currentRow=0;

        //这句代码的作用是清空这个数组以及第二个界面的内容,方便下次使用
        shiftPlanList.clear();
        if (model_2)
        {
            // 清空所有行(保留表头)
            model_2->removeRows(0, model_2->rowCount());
        }
        ui->evaluationInput->clear();
        ui->nameInput->clear();

        addOrRevise_1=0;
    }

这是点了第二个界面的应用按钮之后的槽函数

if(addOrRevise_2==1)
    {
        //这几行代码的作用是获取第三个界面输入框里的文本
        QString startTime=ui->plannextnext_startTimeInput->text();
        QString endTime=ui->plannextnext_endTimeInput->text();
        QString event=ui->plannextnext_eventInput->text();
        QString isSuccess=ui->plannextnext_isSuccessChoice->currentText();

        //这几行代码的作用是向中介数组添加数据
        shiftTaskList.append(startTime);
        shiftTaskList.append(endTime);
        shiftTaskList.append(event);
        shiftTaskList.append(isSuccess);

        //这几行代码的作用是向planDecidetableView里添加一行
        int row = model_2->rowCount();
        model_2->insertRow(row);
        for (int col = 0; col < 4; col++)
        {
            QStandardItem *item = new QStandardItem(shiftTaskList.at(col));
            model_2->setItem(row, col, item);
        }

        //这句代码的作用是清空这个数组以及第三个界面的内容,方便下次使用
        shiftTaskList.clear();
        ui->plannextnext_startTimeInput->setText("");
        ui->plannextnext_endTimeInput->setText("");
        ui->plannextnext_eventInput->setText("");
        ui->plannextnext_isSuccessChoice->setCurrentText(0);

        addOrRevise_2=0;
    }

这是第三个界面的应用按钮的槽函数

核心思路就是上边提到的,在这里着重说一下笔者遇到的困难:

编程前总觉得自己的思路特别完美,但是在没有经验的情况下,考虑难免是不全面的,所以总会出现各种意料之外的问题。笔者对第一个界面的表格操作就是屡屡出错,刚开始先插成一行一行的了 ,后来又把自我评价给覆盖了,后来又出现各种问题。那笔者是怎么解决的呢?就是往进加一些辅助变量,然后再改一下插入逻辑,这个板块越写笔者越觉得像屎山了,现在修改功能还没实现事情就有点超出笔者的控制范围了。

不过没有关系,没有屎山代码的积累就写不出好代码。作为我的处女作,屎山也是很正常的

(4)实现修改

修改功能又比新建功能复杂了一些,因为它还涉及到把表中数据往后边的界面传递。

还是先梳理逻辑:用户按下修改按钮,然后被选中的一列存进第二个界面,标题存在标题输入框,自我评价存在自我评价输入框,每一个任务块一行一行地存,这里肯定也要用一个循环了。然后把这列东西全部删除,点第二个界面的应用按钮后再把这一列加进去,需要注意插入位置一定是选中列;如果在第二个界面用户点击修改,被选中的一行是任务块,然后跳到第三个界面,把这一行的数据存进第三个界面,然后把这行删除,点第三个界面的应用按钮把这一行加进去,插入位置是选中行

//这个函数的作用是修改规划----------------------------------未完成
void Plan::on_revisePlanButton_clicked()
{
    ui->stackedWidget->setCurrentIndex(1);
    addOrRevise_1=2;

    //这个for循环是为了获取当前选中列的最后一行
    int lastRow = 0;
    if (model_1->hasChildren())
    {
        // 从模型底部向上查找第一个有数据的单元格
        for (int i = model_1->rowCount() ; i >= 0; i--)
        {
            if (!model_1->index(i, currentCol).data().isNull())
            {
                lastRow = i;
                break;
            }
        }
    }

    //这几行代码是把标题和自我评价传到第二个界面里
    QModelIndex index = model_1->index(0, currentCol);
    QString title=index.data().toString();
    ui->nameInput->setText(title);

    index=model_1->index(lastRow,currentCol);
    QString evalution=index.data().toString();
    ui->evaluationInput->setText(evalution);

    int currentRow=1;
    //这个while循环的作用是将第一个界面的表格中的每个任务块导入第二个界面的表格中
    while(currentRow<lastRow)
    {
        index=model_1->index(currentRow,currentCol);
        QString startTime = index.data().toString();
        index=model_1->index(currentRow+1,currentCol);
        QString endTime=index.data().toString();
        index=model_1->index(currentRow+2,currentCol);
        QString event=index.data().toString();
        index=model_1->index(currentRow+3,currentCol);
        QString isSuccess=index.data().toString();

        currentRow+=4;

        shiftPlanList.append(startTime);
        shiftPlanList.append(endTime);
        shiftPlanList.append(event);
        shiftPlanList.append(isSuccess);

        //这几行代码的作用是向planDecidetableView里添加一行
        int taskRow = model_2->rowCount();
        model_2->insertRow(taskRow);
        for (int col = 0; col < 4; col++)
        {
            QStandardItem *item = new QStandardItem(shiftPlanList.at(col));
            model_2->setItem(taskRow, col, item);
        }

        shiftPlanList.clear();
    }
}

这个函数的作用是点击第一个界面的修改函数之后把所有数据传进第二个界面中

困难倒是没啥,关键是细节要到位,要不然行和列可能会冲突

else if(addOrRevise_1==2)
    {
        model_1->removeColumn(currentCol);

        //这几行代码的作用是获取第二个界面输入框里的文本
        QString title=ui->nameInput->text();
        QString evalution=ui->evaluationInput->toPlainText();

        int col = currentCol;
        model_1->insertColumn(col);
        QStandardItem *item=new QStandardItem(title);
        model_1->setItem(0,col,item);
        item=new QStandardItem(evalution);
        model_1->setItem(1,col,item);

        int currentRow=0;
        //这个循环的作用是把表格里的内容全部放到第一个界面里
        while(currentRow<model_2->rowCount())
        {
            //这几行代码是向中介数组中导入表格数据
            QModelIndex index = model_2->index(currentRow, 0);
            QString startTime = index.data().toString();
            index=model_2->index(currentRow,1);
            QString endTime=index.data().toString();
            index=model_2->index(currentRow,2);
            QString event=index.data().toString();
            index=model_2->index(currentRow,3);
            QString isSuccess=index.data().toString();

            shiftPlanList.append(startTime);
            shiftPlanList.append(endTime);
            shiftPlanList.append(event);
            shiftPlanList.append(isSuccess);

            //这几行代码的作用是向planShowtableView里添加一个任务块
            int lastRow = 0;
            if (model_1->hasChildren())
            {
                // 从模型底部向上查找第一个有数据的单元格
                for (int i = model_1->rowCount() ; i >= 0; i--)
                {
                    if (!model_1->index(i, col).data().isNull())
                    {
                        lastRow = i; // 找到后,插入位置为这一行
                        break;
                    }
                }
            }
            for (int crow = lastRow,cindex=0; crow < lastRow+4; crow++,cindex++)
            {
                QStandardItem *item = new QStandardItem(shiftPlanList.at(cindex));
                model_1->setItem(crow, col, item);
            }
            QStandardItem *item = new QStandardItem(evalution);
            model_1->setItem(lastRow+4,col,item);

            shiftPlanList.clear();
            currentRow++;
        }

        //把这个索引置零,防止干扰后续操作
        currentRow=0;

        //这句代码的作用是清空这个数组以及第二个界面的内容,方便下次使用
        shiftPlanList.clear();
        if (model_2)
        {
            // 清空所有行(保留表头)
            model_2->removeRows(0, model_2->rowCount());
        }
        ui->evaluationInput->clear();
        ui->nameInput->clear();

        addOrRevise_1=0;
    }

这个函数和新建唯一的区别就是把原列删除,然后把删除那列插一个新的进去。这段代码没有复用我感觉很屎,但是没办法,前期都是这样做的,为了保持架构的统一,还有让我的思路没那么混乱,我决定就这样继续堆屎了

//这个函数的作用是修改已经存在的规划更细致的部分
void Plan::on_reviseProcessButton_clicked()
{
    addOrRevise_2=2;
    ui->stackedWidget->setCurrentIndex(2);

    //这段代码的作用是将表格中被选中的行的内容依次存进中介数组
    if (getCurrentRow != -1)
    {
        for (int col = 0; col < 4; col++)
        {
            QModelIndex index = model_2->index(getCurrentRow, col);
            QVariant data = model_2->data(index);
            shiftTaskList.append(data.toString());
        }
    }
    //这段代码的作用是在界面中设置中介数组中的内容
    ui->plannextnext_startTimeInput->setText(shiftTaskList[0]);
    ui->plannextnext_endTimeInput->setText(shiftTaskList[1]);
    ui->plannextnext_eventInput->setText(shiftTaskList[2]);
    int isSuccessIndex = ui->plannextnext_isSuccessChoice->findText(shiftTaskList[3]);
    if (isSuccessIndex != -1)
    {
        ui->plannextnext_isSuccessChoice->setCurrentIndex(isSuccessIndex);
    }

    //要把中介数组清空,方便下次使用
    shiftTaskList.clear();
}

这是第二个界面的修改按钮的槽函数,作用就是把第二个界面表格中的东西导入第三个界面的输入框中

 else if(addOrRevise_2==2)
    {
        //这段代码的作用是获取当前界面的输入框的内容
        QString startTime=ui->plannextnext_startTimeInput->text();
        QString endTime=ui->plannextnext_endTimeInput->text();
        QString event=ui->plannextnext_eventInput->text();
        QString isSuccess=ui->plannextnext_isSuccessChoice->currentText();

        //这段代码的作用是把捕获到的内容再存进中介数组中
        shiftTaskList.append(startTime);
        shiftTaskList.append(endTime);
        shiftTaskList.append(event);
        shiftTaskList.append(isSuccess);

        //这个循环的作用是把中介数组的内容传进选中的行中
        for (int col = 0; col < 4; col++)
        {
            QStandardItem *item = new QStandardItem(shiftTaskList.at(col));
            model_2->setItem(getCurrentRow, col, item);
        }

        //清空中介数组方便下次使用
        shiftTaskList.clear();

        //将界面置空方便下次使用
        ui->plannextnext_startTimeInput->setText("");
        ui->plannextnext_endTimeInput->setText("");
        ui->plannextnext_eventInput->setText("");
        ui->plannextnext_isSuccessChoice->setCurrentIndex(0);

        //将选择模式置空,防止干扰下次使用
        addOrRevise_2=0;
    }

这个分支就是完成第三个界面的应用,把选中那一行的内容改成第三个界面修改后的内容

篇末总结

做完这个板块笔者又有了很多感悟,也许这是一种厚积薄发?

1.初期编程不难,难的是一直调试改bug,笔者对表格一直不出数据这个问题修改很久

2.人毕竟是有局限性的,一直做下去就会有越来越多的理解,不做的话永远想不到那一步,有些实现逻辑往往是突发奇想的

3.前边的应用按钮槽函数分情况其实是没有必要的,因为修改和新建的区别无非不过就是有没有往后边的界面传数据,这一点在笔者最开始的时候没有意识到,做到后边再梳理逻辑时想明白了

4.中介数组更适合数据集较大时,这样用一个循环比较方便,其实作用并不是很大,那笔者先前认为的天才想法其实也就那样,归根结底是经验不足,对Qt的理解还不到位

5.变量最好不要高一层第一层做同名变量,因为这样很可能分不清,然后出bug找不到;变量能少用就少用,代码复用的时候改的不用那么费劲

6.要注意库函数的传参顺序,可能会出现问题

在这个项目中我的进步很大,越往后做越觉得前期的工作是在堆屎,但是以后我毕竟不会再做C++相关的项目了,所以重构的话可能会是很久以后的事情,现在就往屎山继续堆屎,处女作嘛,屎山很正常,只要我能进步就行了。后续应该会把这个项目传到github上存着,留作纪念

这个板块是目前我事实上做的最难的一个板块,但是花的时间却没有第一个板块多,实现了从无到有之后,难度真的大大减小。

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

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

相关文章

数据分析-图2-图像对象设置参数与子图

from matplotlib import pyplot as mp mp.figure(A figure,facecolorgray) mp.plot([0,1],[1,2]) mp.figure(B figure,facecolorlightgray) mp.plot([1,2],[2,1]) #如果figure中标题已创建&#xff0c;则不会新建窗口&#xff0c; #而是将旧窗口设置为当前窗口 mp.figure(A fig…

查询公网IP地址的方法:查看自己是不是公网ip,附内网穿透外网域名访问方案

本地搭建服务并提供互联网连接时&#xff0c;较为传统的方法是使用公网IP地址。因此&#xff0c;如何查询本地自己是不是公网IP&#xff0c;是必须要掌握的一种技巧。当面对确实无公网IP时&#xff0c;则可以通过内网穿透方案&#xff0c;如nat123网络映射工具&#xff0c;将本…

Redis学习打卡-Day1-SpringDataRedis、有状态无状态

Redis的Java客户端 Jedis 以 Redis 命令作为方法名称&#xff0c;学习成本低&#xff0c;简单实用。Jedis 是线程不安全的&#xff0c;并且频繁的创建和销毁连接会有性能损耗&#xff0c;因此推荐使用 Jedis 连接池代替Jedis的直连方式。 lettuce Lettuce是基于Netty实现的&am…

Spring Spring Boot 常用注解整理

Spring & Spring Boot 常用注解整理 先理解核心概念&#xff1a;什么是注解&#xff08;Annotation&#xff09;&#xff1f;第一部分&#xff1a;IOC&#xff08;控制反转&#xff09;和 DI&#xff08;依赖注入&#xff09;1. Component2. Service, Repository, Controll…

c#建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能

# financial_建筑行业 建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能 # 开发背景 软件是给岳阳客户定制开发一款建筑行业流水账财务软件。提供工程签证单、施工日志、人员出勤表等信息记录。 # 财务管理系统功能描述 1.可以自行设置记账科目&#xff0c;做凭…

让 Cursor 教我写 MCP Client

文章目录 1. 写在最前面2. 动手实现一个 MCP Client2.1 How 天气查询 Client2.1.1 向 Cursor 提问的艺术2.1.2 最终成功展示2.1.3 client 的代码 3. MCP 协议核心之一总结3.1 SSE vs WebSocket 4. 碎碎念5. 参考资料 1. 写在最前面 学习了 MCP Server 的实现后&#xff0c;刚好…

反射, 注解, 动态代理

文章目录 单元测试什么是单元测试咱们之前是如何进行单元测试的&#xff1f; 有啥问题 &#xff1f;现在使用方法进行测试优点Junit单元测试的使用步骤删除不需要的jar包总结 反射认识反射、获取类什么是反射反射具体学什么&#xff1f;反射第一步&#xff1a;或者Class对象 获…

vue vite 无法热更新问题

一、在vue页面引入组件CustomEmployeesDialog&#xff0c;修改组件CustomEmployeesDialog无法热更新 引入方式&#xff1a; import CustomEmployeesDialog from ../dialog/customEmployeesDialog.vue 目录结构&#xff1a; 最后发现是引入import时&#xff0c;路径大小写与目…

深度学习中的查全率与查准率:如何实现有效权衡

&#x1f4cc; 友情提示&#xff1a; 本文内容由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;创作平台的gpt-4-turbo模型辅助生成&#xff0c;旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证&#xff0c;建议读者通过官方文档或实践进一步确认…

Windows玩游戏的时候,一按字符键就显示桌面

最近打赛伯朋克 2077 的时候&#xff0c;不小心按错键了&#xff0c;导致一按字符键就显示桌面。如下&#xff1a; 一开始我以为是输入法的问题&#xff08;相信打游戏的人都知道输入法和奔跑键冲突的时候有多烦&#xff09;&#xff0c;但是后来解决半天发现并不是。在网上搜…

Gemini 2.5 Flash和Pro预览版价格以及上下文缓存的理解

Gemini 2.5 Flash和Pro预览版价格 Gemini 2.5 Flash 预览版就是 Google 的最新 AI 大模型&#xff0c;能处理巨量内容。可以免费体验&#xff0c;但有次数和功能上的限制&#xff1b;付费层级才开放全部高级功能。价格也比传统 API 略有不同&#xff0c;尤其在“思考预算”“上…

vue2 头像上传+裁剪组件封装

背景&#xff1a;最近在进行公司业务开发时&#xff0c;遇到了头像上传限制尺寸的需求&#xff0c;即限制为一寸证件照&#xff08;宽295像素&#xff0c;高413像素&#xff09;。 用到的第三方库&#xff1a; "vue-cropper": "^0.5.5" 完整组件代码&…

AI-02a5a5.神经网络-与学习相关的技巧-权重初始值

权重的初始值 在神经网络的学习中&#xff0c;权重的初始值特别重要。实际上&#xff0c;设定什么样的权重初始值&#xff0c;经常关系到神经网络的学习能否成功。 不要将权重初始值设为 0 权值衰减&#xff08;weight decay&#xff09;&#xff1a;抑制过拟合、提高泛化能…

【springcloud学习(dalston.sr1)】Eureka单个服务端的搭建(含源代码)(三)

该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍&#xff08;含源代码&#xff09;&#xff08;一&#xff09; 这篇文章主要介绍单个eureka服务端的集群环境是如何搭建的。 通过前面的文章【springcloud学习(dalston.sr1)】…

Node.js数据抓取技术实战示例

Node.js常用的库有哪些呢&#xff1f;比如axios或者node-fetch用来发送HTTP请求&#xff0c;cheerio用来解析HTML&#xff0c;如果是动态网页的话可能需要puppeteer这样的无头浏览器。这些工具的组合应该能满足大部分需求。 然后&#xff0c;可能遇到的难点在哪里&#xff1f;…

windows10 安装 QT

本地环境有个qt文件&#xff0c;这里是5.14.2 打开一个cmd窗口并指定到该文件根目录下 .\qt-opensource-windows-x86-5.14.2.exe --mirror https://mirrors.ustc.edu.cn/qtproject 执行上面命令 记住是文件名&#xff0c;记住不要傻 X的直接复制&#xff0c;是你的文件名 点击…

WordPress 和 GPL – 您需要了解的一切

如果您使用 WordPress&#xff0c;GPL 对您来说应该很重要&#xff0c;您也应该了解它。查看有关 WordPress 和 GPL 的最全面指南。 您可能听说过 GPL&#xff08;通常被称为 WordPress 的权利法案&#xff09;&#xff0c;但很可能并不完全了解它。这是有道理的–这是一个复杂…

C++书本摆放 2024年信息素养大赛复赛 C++小学/初中组 算法创意实践挑战赛 真题详细解析

目录 C++书本摆放 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、运行结果 五、考点分析 六、 推荐资料 1、C++资料 2、Scratch资料 3、Python资料 C++书本摆放 2024年信息素养大赛 C++复赛真题 一、题目要求 1、编程实现 中科智慧科技…

RabbitMQ 核心概念与消息模型深度解析(一)

一、RabbitMQ 是什么 在当今分布式系统盛行的时代&#xff0c;消息队列作为一种至关重要的中间件技术&#xff0c;扮演着实现系统之间异步通信、解耦和削峰填谷等关键角色 。RabbitMQ 便是消息队列领域中的佼佼者&#xff0c;是一个开源的消息代理和队列服务器&#xff0c;基于…

论文阅读笔记——双流网络

双流网络论文 视频相比图像包含更多信息&#xff1a;运动信息、时序信息、背景信息等等。 原先处理视频的方法&#xff1a; CNN LSTM&#xff1a;CNN 抽取关键特征&#xff0c;LSTM 做时序逻辑&#xff1b;抽取视频中关键 K 帧输入 CNN 得到图片特征&#xff0c;再输入 LSTM&…