基于Qt的app开发第七天

news2025/5/14 13:34:29

写在前面

        笔者是大一下计科生,标题这个项目是笔者这个学期的课设,与学长共创,我负责客户端部分,现在已经实现了待办板块的新建、修改。         

        这个项目目前已经走上正轨了,博主也实现了主要功能的从无到有,现在做打卡板块类似的功能也会很容易,所以这篇博客记录打卡板块功能的初步实现

功能分析

本次主要实现修改控件、打卡块的新建和修改、总时长的计算、是否达标的确认

至于调用系统时钟这个功能后续再做,还有打卡天数自增因为要结合当前时间也是后续再做

思路梳理

这个思路参照待办板块的话是很好实现的,若今日是否达标选了是,则天数+1,选了否,天数清零

打卡块还是用tableView这个控件,用QList型成员变量当中介

计算总时长就是把表中每一个时间段转换为int型,再计算总时长

项目没有什么难点,开始做

具体实现

(1)修改控件

把记录天数的地方改成LineEdit,日期改成LineEdit,任务块改成tableView,修改挪到下边,今日总时长改成LineEdit,今日是否达标设置两个选项,默认为否

记得修改控件的名字

(2)设置成员变量

目前需要一个记录总天数的成员变量、记录总时长的成员变量、建立表格用的模型、模式选择器、选中行索引、中介变量

这段代码写在h文件里:

    int allDays;
    int allHours;
    int allMinutes;
    QStandardItemModel *model = new QStandardItemModel(this);    
    int addOrRevise;
    int currentRow;
    QTime shiftEndTime;
    QTime shiftstartTime;
    QString shiftEvent;

(3)初始化表格

仿照待办板块做就行了

//这个函数的作用是获取并初始化TableView控件
void Clock::GetclockShowTableView()
{
    //获取界面中的表格对象
    QTableView *clockShow = ui->clockShowTableView;
    
    //设置clockShowTableView的表头
    model->setColumnCount(3);
    model->setHorizontalHeaderLabels({"开始时间","结束时间","事项"});
    
    //设置表格的点击模式
    ui->clockShowTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->clockShowTableView->setSelectionMode(QAbstractItemView::SingleSelection);
    
    clockShow->setModel(model);
}

这个函数在clock的构造函数里调用

(4)实现新建修改

这部分还是仿照待办直接做就行

这里有一个需要注意的地方:待办板块的始末时间咋样都无所谓,反正用户能看懂就行,但是打卡板块是要计算一天的总时长的,所以打卡这里要改成时间输入框或按标准格式输入

使用timeEdit控件,然后对应获取代码也要改一下,中介变量也不能是动态数组型的了,而是两个QTime型的和一个QString型的

附一下各个部分的代码:

//这个函数的作用是新建一个打卡的事件
void Clock::on_newClockButton_clicked()
{
    ui->stackedWidget->setCurrentIndex(1);

    addOrRevise=1;
}
//这个函数的作用是修改已经存在的打卡事件
void Clock::on_reviseButton_clicked()
{
    //这段代码的作用是将表格中被选中的行的内容依次存进中介数组
    if (currentRow != -1)
    {
        QModelIndex index = model->index(currentRow, 0);
        QVariant data = model->data(index);
        shiftStartTime=(data.toTime());
        index = model->index(currentRow, 1);
        data = model->data(index);
        shiftEndTime=(data.toTime());
        index = model->index(currentRow, 2);
        data = model->data(index);
        shiftEvent=(data.toString());
    }
    //这段代码的作用是在界面中设置中介数组中的内容
    ui->startTimeInput->setTime(shiftStartTime);
    ui->endTimeInput->setTime(shiftEndTime);
    ui->eventInput->setText(shiftEvent);

    //要把中介变量清空,方便下次使用
    shiftStartTime=QTime(0,0);
    shiftEndTime=QTime(0,0);
    shiftEvent="";

    ui->stackedWidget->setCurrentIndex(1);
}
//这个函数的作用是保存修改或新建的打卡事件------------------------未完成
void Clock::on_clock_applyButton_clicked()
{
    ui->stackedWidget->setCurrentIndex(0);
    if(addOrRevise==1)
    {
        //这几行代码的作用是获取第二个界面输入框里的文本
        QTime startTime=ui->startTimeInput->time();
        QTime endTime=ui->endTimeInput->time();
        QString event=ui->eventInput->text();

        //这几行代码的作用是向tableView里添加一行
        int row = model->rowCount();
        model->insertRow(row);
        QStandardItem *item = new QStandardItem(startTime.toString());
        model->setItem(row, 0, item);
        item = new QStandardItem(endTime.toString());
        model->setItem(row, 1, item);
        item = new QStandardItem(event);
        model->setItem(row, 2, item);


        //这句代码的作用是清空第二个界面的内容,方便下次使用
        QTime orignalTime = QTime(0,0);
        ui->startTimeInput->setTime(orignalTime);
        ui->endTimeInput->setTime(orignalTime);
        ui->eventInput->setText("");

        addOrRevise=0;
    }
    else if(addOrRevise==2)
    {
        //这段代码的作用是获取当前界面的输入框的内容
        QTime startTime=ui->startTimeInput->time();
        QTime endTime=ui->endTimeInput->time();
        QString event=ui->eventInput->text();

        //这个循环的作用是把中介变量的内容传进选中的行中
        QStandardItem *item = new QStandardItem(startTime.toString());
        model->setItem(currentRow, 0, item);
        item = new QStandardItem(endTime.toString());
        model->setItem(currentRow, 1, item);
        item = new QStandardItem(event);
        model->setItem(currentRow, 2, item);


        //将界面置空方便下次使用
        QTime orignalTime=QTime(0,0);
        ui->startTimeInput->setTime(orignalTime);
        ui->endTimeInput->setTime(orignalTime);
        ui->eventInput->setText("");

        //将选择模式置空,防止干扰下次使用
        addOrRevise=0;
    }
}
//这个函数的作用是标记被选中的行并把模式改成修改
void Clock::on_clockShowTableView_clicked(const QModelIndex &index)
{
    currentRow = index.row();
    addOrRevise = 2;
}

(5)当天总时长计算

因为我们的时间输入框是QTime型的,所以可以直接提取出小时和分钟数,这个比较容易实现

关键在于要在点击了新建一个东西或修改一个东西应用按钮之后的数据更新

所以这个功能的实现逻辑应该放在应用按钮的槽函数那里

//以下代码的功能是实现当天总时长的更新--------------------------------------------------当天时间过了十二点自动清空功能未实现
        int startHour=startTime.hour();
        int endMinute=endTime.minute();
        int startMinute=startTime.minute();
        int endHour=endTime.hour();
        if(endMinute>=startMinute)
        {
            allHours+=endHour-startHour;
            allMinutes+=endMinute-startMinute;
            if(allMinutes>=60)
            {
                allMinutes-=60;
                allHours++;
            }
        }
        else
        {
            allHours+=endHour-startHour-1;
            allMinutes+=endMinute+60-startMinute;
            if(allMinutes>=60)
            {
                allMinutes-=60;
                allHours++;
            }
        }
        QString hour=QString::number(allHours);
        QString minute=QString::number(allMinutes);
        ui->hourShowEdit->setText(hour);
        ui->minuteShowEdit->setText(minute);

这是新建的计数功能

解释一下:按下了应用按钮之后,开始计算这段时间的时长,然后把它们转成字符串型放到输出框

//这段代码的作用是减去被修改的时间段
    int startHour=shiftStartTime.hour();
    int endMinute=shiftEndTime.minute();
    int startMinute=shiftStartTime.minute();
    int endHour=shiftEndTime.hour();
    int subHour,subMinute;
    if(endMinute>=startMinute)
    {
        subHour=endHour-startHour;
        subMinute=endMinute-startMinute;
        if(subMinute>=60)
        {
            subMinute-=60;
            subHour++;
        }
    }
    else
    {
        subHour=endHour-startHour-1;
        subMinute=endMinute+60-startMinute;
        if(subMinute>=60)
        {
            subMinute-=60;
            subHour++;
        }
    }
    allHours-=subHour;
    allMinutes-=subMinute;

这是修改按钮按下之后的事情,就是记录一下被修改这个时间段有多长时间,然后把这段扣掉

//以下代码的功能是实现当天总时长的更新--------------------------------------------------当天时间过了十二点自动清空功能未实现
        int startHour=startTime.hour();
        int endMinute=endTime.minute();
        int startMinute=startTime.minute();
        int endHour=endTime.hour();
        if(endMinute>=startMinute)
        {
            allHours+=endHour-startHour;
            allMinutes+=endMinute-startMinute;
            if(allMinutes>=60)
            {
                allMinutes-=60;
                allHours++;
            }
        }
        else
        {
            allHours+=endHour-startHour-1;
            allMinutes+=endMinute+60-startMinute;
            if(allMinutes>=60)
            {
                allMinutes-=60;
                allHours++;
            }
        }
        QString hour=QString::number(allHours);
        QString minute=QString::number(allMinutes);
        ui->hourShowEdit->setText(hour);
        ui->minuteShowEdit->setText(minute);

这段和新建的一样了,因为被修改的已经被扣掉了,所以完全相当于再新建了一个

篇末总结

这个板块的功能我实现得非常顺,为什么呢?当已经梳理清楚逻辑关系之后,敲代码反倒是简单的事情了。重要的是思想,而这个思想又要和计算机相符合

沉浸在项目中时不会察觉外界的变化,我完成了这篇博客时才发现自我打开电脑已经过去了五个小时,根本就察觉不到时间过那么快。

程序员面对的就是无穷无尽的困难和弯路,只有多做才能越来越好,不断积累项目经验才能成为优秀程序员。

这个项目的客户端全程是我自己实现的,辅助我的只有Qt基础教学的网课和学长的一句提点,以及AI告诉我的库函数。从需求文档到代码结构到具体实现都是我来做的。感觉自己摸索很慢很歪但是能学到很多东西,笔者后续学java就不用这样了,毕竟java的资源可是细致又全面的

最后说一下笔者对编程实质的一点愚见:编程就是为了更好地实现增删改查。数据结构和算法是为了提高速度,微服务、高并发等最终目的也是为了更好地实现增删改查,而一个程序员的水平就是由这些增删改查的优化来决定的

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

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

相关文章

目标检测任务常用脚本1——将YOLO格式的数据集转换成VOC格式的数据集

在目标检测任务中,不同框架使用的标注格式各不相同。常见的框架中,YOLO 使用 .txt 文件进行标注,而 PASCAL VOC 则使用 .xml 文件。如果你需要将一个 YOLO 格式的数据集转换为 VOC 格式以便适配其他模型,本文提供了一个结构清晰、…

NLTK库: 数据集3-分类与标注语料(Categorized and Tagged Corpora)

NLTK库: 数据集3-分类与标注语料(Categorized and Tagged Corpora) 1.二分类语料 主要是电影语料,和情绪(积极消极、主观客观)有关,有以下2个语料: 1.1 movie_reviews: IMDb 影评 IMDb(Internet Movie …

uni-app学习笔记五-vue3响应式基础

一.使用ref定义响应式变量 在组合式 API 中&#xff0c;推荐使用 ref() 函数来声明响应式状态&#xff0c;ref() 接收参数&#xff0c;并将其包裹在一个带有 .value 属性的 ref 对象中返回 示例代码&#xff1a; <template> <view>{{ num1 }}</view><vi…

ElasticSeach快速上手笔记-入门篇

由来 Elasticsearch 是一个基于 Apache Lucene 构建的分布式、高扩展、近实时的搜索与数据分析引擎&#xff0c;能够高效处理结构化和非结构化数据的全文检索及复杂分析 搜索&#xff0c;即用户在平台如百度进行输入关键词&#xff0c;由后端给出搜索结果数据进行返回&#x…

《ffplay 读线程与解码线程分析:从初始化到 seek 操作,对比视频与音频解码的差异》

1 read-thread 1.1 初始化部分 1.分配. avformat_alloc_context 创建上下⽂ ic avformat_alloc_context();if (!ic) {av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");ret AVERROR(ENOMEM);goto fail;}2 ic->interrupt_callback.callback deco…

MySQL推荐书单:从入门到精通

给大家介绍一些 MySQL 从入门到精通的经典书单&#xff0c;可以基于不同学习阶段的需求进行选择。 入门 MySQL必知必会 这本书继承了《SQL必知必会》的优点&#xff0c;专门针对 MySQL 用户&#xff0c;没有过多阐述数据库基础理论&#xff0c;而是紧贴实战&#xff0c;直接从…

【Nacos】env NACOS_AUTH_TOKEN must be set with Base64 String.

【Nacos】env NACOS_AUTH_TOKEN must be set with Base64 String. 问题描述 env NACOS_AUTH_TOKEN must be set with Base64 String.原因分析 从错误日志中可以看出&#xff0c;Nacos 启动失败的原因是缺少必要的环境变量 NACOS_AUTH_TOKEN。 NACOS_AUTH_TOKEN: Nacos 用于生…

秋招准备——2.跨时钟相关

格雷码异步FIFO跨时钟域处理 格雷码 一、格雷码规律 相邻性&#xff1a;相邻两个数的格雷码只有一位不同&#xff0c;例如&#xff1a; 0000 → 0001&#xff08;仅最低位变化&#xff09;0001 → 0011&#xff08;仅次低位变化&#xff09;0011 → 0010&#xff08;仅最低位…

激光打印机常见打印故障简单处理意见

一、 问题描述&#xff1a; 给打印机更换新的硒鼓时拉开硒鼓封条时有微量碳粉带出&#xff1b; 原因&#xff1a; 出厂打印测试时&#xff0c;可能会有微量碳粉在磁辊上或者磁辊仓&#xff1b; 解决方法&#xff1a; 擦干净即可正常使用&#xff1b; 二、 问题描述&…

【2025最新】Windows系统装VSCode搭建C/C++开发环境(附带所有安装包)

文章目录 为什么选择VSCode作为C/C开发工具&#xff1f;一、VSCode安装过程&#xff08;超简单&#xff01;&#xff09;二、VSCode中文界面设置&#xff08;再也不用对着英文发愁&#xff01;&#xff09;三、安装C/C插件&#xff08;编程必备神器&#xff01;&#xff09;四、…

MYSQL 查询去除小数位后多余的0

MYSQL 查询去除小数位后多余的0 在MySQL中&#xff0c;有时候我们需要去除存储在数据库中的数字字段小数点后面多余的0。这种情况通常发生在处理金额或其他需要精确小数位的数据时。例如&#xff0c;数据库中存储的是decimal (18,6)类型的数据&#xff0c;但在页面展示时不希望…

基于GF域的多进制QC-LDPC误码率matlab仿真,译码采用EMS算法

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 本课题实现的是四进制QC-LDPC 仿真操作步骤可参考程序配套的操作视频。 2.算…

Vitrualbox完美显示系统界面(只需三步)

目录 1.使用vitrualbox的增强功能&#xff1a;​编辑 2.安装增强功能&#xff08;安装完后要重启虚拟机&#xff09;&#xff1a; 3. 调整界面尺寸&#xff08;如果一个选项不行的话&#xff0c;就多试试其他不同的百分比&#xff09;&#xff1a; 先看看原来的&#xff0c;…

王炸组合!STL-VMD二次分解 + Informer-LSTM 并行预测模型

往期精彩内容&#xff1a; 单步预测-风速预测模型代码全家桶-CSDN博客 半天入门&#xff01;锂电池剩余寿命预测&#xff08;Python&#xff09;-CSDN博客 超强预测模型&#xff1a;二次分解-组合预测-CSDN博客 VMD CEEMDAN 二次分解&#xff0c;BiLSTM-Attention预测模型…

n8n 修改或者智能体用文档知识库创建pdf

以下是对 Nextcloud、OnlyOffice、Seafile、Etherpad、BookStack 和 Confluence 等本地部署文档协作工具的综合评测、对比分析和使用推荐&#xff0c;帮助您根据不同需求选择合适的解决方案。 &#x1f9f0; 工具功能对比 工具名称核心功能本地部署支持适用场景优势与劣势Next…

论坛系统(中-1)

软件开发 编写公共代码 定义状态码 对执⾏业务处理逻辑过程中可能出现的成功与失败状态做针对性描述(根据需求分析阶段可以遇见的问题提前做出定义)&#xff0c;⽤枚举定义状态码&#xff0c;先定义⼀部分&#xff0c;业务中遇到新的问题再添加 定义状态码如下 状态码类型描…

FPGA+ESP32 = GameBoy 是你的童年吗?

之前介绍的所有的复古游戏机都是基于Intel-Altera FPGA制作的&#xff0c;今天就带来一款基于AMD-Xilinx FPGA的复古掌上游戏机-Game Bub。 Game Bub是一款掌上游戏机&#xff0c;旨在畅玩 Game Boy、Game Boy Color 和 Game Boy Advance 游戏。与大多数现代掌上游戏机一样&…

3D迷宫探险:伪3D渲染与运动控制的数学重构

目录 3D迷宫探险:伪3D渲染与运动控制的数学重构引言第一章 伪3D渲染引擎1.1 射线投射原理1.2 纹理透视校正第二章 迷宫生成算法2.1 图论生成模型2.2 复杂度控制第三章 第一人称控制3.1 运动微分方程3.2 鼠标视角控制第四章 碰撞检测优化4.1 层级检测体系4.2 滑动响应算法第五章…

【金仓数据库征文】_金仓数据库在金融行业的两地三中心容灾架构实践

金仓数据库在金融行业的两地三中心容灾架构实践 &#x1f31f;嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 引言 随着国家对信息技术应用创新&#xff0…

Python作业练习3

任务简述 字符田字格绘制 代码实现 def print_tianzige():for i in range(11):if i in [0, 5, 10]:print("" "-----" * 2)else:print("|" " |" * 2)print_tianzige() 结果展示