基于 QT 实现 Task Timer,高效利用时间
一、开发环境
Ubuntu 20.04
QT6.0
二、新建 Qt Wigets Application
这里的基类选择 Wigets,


pro 配置文件添加 sql 模块,需要用到 sqlite,
QT += sql

三、添加数据库连接头文件

// connection.h
#ifndef CONNECTION_H
#define CONNECTION_H#include <QMessageBox>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>static bool createConnection()
{QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName(":memory:");//db.setDatabaseName("ikun.db");bool res = db.open();if (res){qDebug() << "open ikun.db ok !";}else{qDebug() << "open ikun.db fail: " << db.lastError().text();}QSqlQuery query;if(!query.exec("create table task_history(id INTEGER PRIMARY KEY AUTOINCREMENT,task_name varchar(200) not null, cost_time varchar(20) not null, create_time varchar(25) not null)")){qDebug() << "create table task_history error: " << query.lastError().text();}return true;
}
#endif // CONNECTION_H
初始化连接到 sqlite 数据库,这里使用的内存数据库,没有持久化到磁盘,连接数据库之后创建了一个表 task_history ,主键为 id 自增,任务事项 task_name 以及消耗时间 cost_time,
四、布局设计
一个 QLineEdit 用于输入任务事项,一个 QLCDNumber 用于计时,一个 QPlainTextEdit 用于输出日志,两个 QPushButton 用于操作开始计时和终止计时,


除了组件的布局调整,还需要在主窗体新增一个槽函数 on_Widget_customContextMenuRequested ,在添加右键菜单功能时需要用到,
五、修改 widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QDateTime>
#include <QTimer>
#include <QTime>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
protected:void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void paintEvent(QPaintEvent *);
protected:QPoint pos;QTimer * timer;QTime * timeRecord;bool isStart;
private slots:void update_time();void on_start_btn_clicked();void get_todo_summary();void on_end_btn_clicked();void on_Widget_customContextMenuRequested(const QPoint &pos);private:Ui::Widget *ui;
};
#endif // WIDGET_H
头文件中主要定义了计时器的成员属性与成员方法、鼠标事件、绘画事件以及对应的槽方法,
六、修改 widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <qpainter.h>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QMessageBox>
#include <QMenu>
#include <QSqlQueryModel>
#include <QTableView>
#include <QDateTime>
#include <QScreen>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowFlag(Qt::FramelessWindowHint);this->setAttribute(Qt::WA_TranslucentBackground);this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);// initthis->isStart = false;this->timer = new QTimer;this->timeRecord = new QTime(0, 0, 0);// connect timer and SLOT functionconnect(this->timer,SIGNAL(timeout()),this,SLOT(update_time()));// menuthis->setContextMenuPolicy(Qt::CustomContextMenu);
}Widget::~Widget()
{delete ui;
}void Widget::mousePressEvent(QMouseEvent* ev)
{if(ev->button()==Qt::LeftButton){pos=ev->pos();}
}void Widget::mouseMoveEvent(QMouseEvent*ev)
{if(ev->buttons()==Qt::LeftButton){int x,y;x=ev->pos().x()-pos.x();y=ev->pos().y()-pos.y();this->move(this->x()+x,this->y()+y);}
}void Widget::paintEvent(QPaintEvent *)
{QPainter painter(this);QPixmap pixmap;pixmap.load(QString("../MyPet/image/pikakun.png"));painter.drawPixmap(0, 0, 128, 128, pixmap);
}void Widget::on_start_btn_clicked()
{if(this->ui->todo_line->text().trimmed().length() == 0 ){QMessageBox::warning(this, tr("warning"), tr("please input todo first!"), QMessageBox::Yes);this->ui->todo_line->setFocus();return;}this->ui->todo_line->setEnabled(false);this->ui->last_log->setPlainText(QString("Mission " + this->ui->todo_line->text().trimmed() + " is timing..."));if(!this->isStart){this->timer->start(128);this->ui->start_btn->setText(QString("Pause"));}else{this->timer->stop();this->ui->start_btn->setText(QString("Continue"));}this->isStart = !this->isStart;
}void Widget::update_time()
{// timer add 1 secs, and then display*this->timeRecord = this->timeRecord->addMSecs(128);this->ui->timer->display(this->timeRecord->toString(QString("hh:mm:ss.zzz")));
}void Widget::on_end_btn_clicked()
{// stop timerthis->timer->stop();// show logthis->ui->last_log->setPlainText(QString(this->ui->todo_line->text() +" Cost Time " +this->timeRecord->toString(QString("hh:mm:ss.zzz"))));// save dbQSqlDatabase::database().transaction();QSqlQuery query;query.prepare(QString("insert into task_history(task_name, cost_time, create_time ) ""values(:task_name, :cost_time,:create_time)"));query.bindValue(":task_name", this->ui->todo_line->text());query.bindValue(":cost_time", this->timeRecord->toString(QString("hh:mm:ss.zzz")));QDateTime dt =QDateTime::currentDateTime();// format yyyy//MM/dd hh:mm:s.zzzQString create_time = dt.toString("yyyy-MM-dd hh:mm:ss.zzz");query.bindValue(":create_time", create_time);if(!query.exec()){qDebug() << "insert into task_history error: " << query.lastError().text();}QSqlDatabase::database().commit();// reset displaythis->timeRecord->setHMS(0,0,0);this->ui->timer->display(this->timeRecord->toString(QString("hh:mm:ss.zzz")));this->isStart = false;this->ui->start_btn->setText(QString("Start"));// reset todo_linethis->ui->todo_line->clear();this->ui->todo_line->setEnabled(true);this->ui->todo_line->setFocus();
}void Widget::get_todo_summary()
{QSqlQueryModel *model = new QSqlQueryModel(this);model->setQuery("select * from task_history");model->setHeaderData(0, Qt::Horizontal, tr("ID"));model->setHeaderData(1, Qt::Horizontal, tr("Task"));model->setHeaderData(2, Qt::Horizontal, tr("Time"));model->setHeaderData(3, Qt::Horizontal, tr("LogTime"));QTableView *view = new QTableView;view->setWindowTitle(QString("summary"));view->setModel(model);// must after setModelview->setColumnWidth(1,250);view->setColumnWidth(3,150);QSize *min_size = new QSize;min_size->setWidth(620);min_size->setHeight(400);view->setMinimumSize(*min_size);QScreen *screen = QApplication::primaryScreen();QSize screenSize = screen->size();view->move(( screenSize.width() - min_size->width() ) / 2 , ( screenSize.height() - view->height() ) / 2 );view->show();// free memdelete min_size;
}void Widget::on_Widget_customContextMenuRequested(const QPoint &pos)
{QMenu *menu = new QMenu(this);QAction *summary = new QAction( QIcon(QString("../MyPet/image/pikakun.png")),tr("summary"), this);menu->addAction(summary);connect(summary, SIGNAL(triggered()), this, SLOT(get_todo_summary()));menu->exec(cursor().pos());
}
七、修改 main.cpp
初始化数据库连接,并将窗口移动至屏幕的中间位置,
#include "widget.h"
#include "connection.h"
#include <QApplication>
#include <QLocale>
#include <QTranslator>
#include <QScreen>int main(int argc, char *argv[])
{QApplication a(argc, argv);if (!createConnection()){return 1;}QTranslator translator;const QStringList uiLanguages = QLocale::system().uiLanguages();for (const QString &locale : uiLanguages) {const QString baseName = "MyPet_" + QLocale(locale).name();if (translator.load(":/i18n/" + baseName)) {a.installTranslator(&translator);break;}}Widget w;QScreen *screen = QApplication::primaryScreen();QSize screenSize = screen->size();w.move(( screenSize.width() - w.width() ) / 2 , ( screenSize.height() - w.height() ) / 2 );w.show();return a.exec();
}
八、效果演示

1、输入需要计时的事项后,点击“Start”按钮开始计时
2、开始计时后,“Start”按钮会变成“Pause”按钮,点击该按钮会暂停计时
3、暂停后,“Pause”按钮会变成“Continue”按钮,点击该按钮会继续计时
4、点击“End”按钮后,停止计时,并记录事项耗时到 sqlite 数据库中
5、右键有“Summary”菜单,点击后可以看到事项汇总
特别注意,如果需要将数据从内存中持久化到硬盘,则修改 connection.h,
# 保存在内存,注释这行
// db.setDatabaseName(":memory:");# 保存在 ikun.db,添加这行
db.setDatabaseName("ikun.db");相关文章:
基于 QT 实现 Task Timer,高效利用时间
一、开发环境 Ubuntu 20.04 QT6.0 二、新建 Qt Wigets Application 这里的基类选择 Wigets, pro 配置文件添加 sql 模块,需要用到 sqlite, QT sql 三、添加数据库连接头文件 // connection.h #ifndef CONNECTION_H #define CONNECTION_…...
图像处理与计算机视觉--第五章-图像分割-霍夫变换
文章目录 1.霍夫变换(Hough Transform)原理介绍2.霍夫变换(Hough Transform)算法流程3.霍夫变换(Hough Transform)算法代码4.霍夫变换(Hough Transform)算法效果 1.霍夫变换(Hough Transform)原理介绍 Hough Transform是一种常用的计算机视觉图形检验方法,霍夫变换一…...
linux下文件操作命令
title: linux下文件操作命令 createTime: 2020-10-29 18:05:52 updateTime: 2020-10-29 18:05:52 categories: linux tags: Linux下文件操作命令 tar命令 使用tar命令一般打包分为两种*.tar ,*.tar.gz 相信大家也使用过tar -zcvf test.tar test/tar -zcvf test.tar.gz test/…...
Golang语法、技巧和窍门
Golang简介 命令式语言静态类型语法标记类似于C(但括号较少且没有分号),结构类似Oberon-2编译为本机代码(没有JVM)没有类,但有带有方法的结构接口没有实现继承。不过有type嵌入。函数是一等公民函数可以返…...
Grander因果检验(格兰杰)原理+操作+解释
笔记来源: 1.【传送门】 2.【传送门】 前沿原理介绍 Grander因果检验是一种分析时间序列数据因果关系的方法。 基本思想在于,在控制Y的滞后项 (过去值) 的情况下,如果X的滞后项仍然有助于解释Y的当期值的变动,则认为 X对 Y产生…...
Python-Flask:编写自动化连接demo脚本:v1.0.0
主函数: # _*_ Coding : UTF-8 _*_ # Time : 13:14 # Author : YYZ # File : Flask # Project : Python_Project_爬虫 import jsonfrom flask import Flask,request,jsonify import sshapi Flask(__name__)# methods: 指定请求方式 接口解析参数host host_info[…...
kafka客户端应用参数详解
一、基本客户端收发消息 Kafka提供了非常简单的客户端API。只需要引入一个Maven依赖即可: <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka_2.13</artifactId><version>3.4.0</version></depend…...
Apache Doris 行列转换可以这样玩
行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧。 行列转换就是如下图所示两种展示形式的互相转换 1. 行转列 我们来看一个简单的例子,我们要把下面这个表的数据,转换成图二的样式 image-20230914151818953.png …...
【Qt图形视图框架】自定义QGraphicsItem和QGraphicsView,实现鼠标(移动、缩放)及键盘事件、右键事件
自定义QGraphicsItem和QGraphicsView 说明示例myitem.hmyitem.cppmyview.hmyview.cpp调用main.cpp 效果 说明 在使用Qt的图形视图框架实现功能时,一般会在其基础上进行自定义功能实现。 如:滚轮对场景的缩放,鼠标拖动场景中的项,…...
C语言结构体指针学习
结构体变量存放内存中,也有起始地址,定义一个变量来存放这个地址,那这个变量就是结构体指针; typedef struct mydata{int a1;int a2;int a3; }mydata;void CJgtzzView::OnDraw(CDC* pDC) {CJgtzzDoc* pDoc GetDocument();ASSERT…...
华为云云耀云服务器L实例评测|部署在线轻量级备忘录 memos
华为云云耀云服务器L实例评测|部署在线轻量级备忘录 memos 一、云耀云服务器L实例介绍1.1 云服务器介绍1.2 产品优势1.3 应用场景1.4 支持镜像 二、云耀云服务器L实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 memos3.1 memos介绍3.2 Docker 环境搭建…...
详解Avast Driver Updater:电脑驱动更新工具的利器还是多余的软件?
亲爱的读者朋友们,你是不是经常为电脑的驱动问题而烦恼?如果是的话,你可能会对这款软件——Avast Driver Updater 电脑驱动更新工具感兴趣。但在你决定尝试之前,不妨先和我一起深入探讨一下它的优点、缺点以及它适用的使用场景。 …...
大数据Flink(九十五):DML:Window TopN
文章目录 DML:Window TopN DML:Window TopN Window TopN 定义(支持 Streaming):Window TopN 是一种特殊的 TopN,它的返回结果是每一个窗口内的 N 个最小值或者最大值。 应用场景...
使用OKHttpClient访问网络
使用OKHttpClient前要引入依赖: 在build.gradle(Moduel :app)中添加 implementation com.squareup.okhttp3:okhttp:3.14.1 implementation com.squareup.okhttp3:logging-interceptor:3.14.1 implementation com.squareup.okio:okio:1.6.0 1. GET(同步…...
maui 开发AMD CPU踩的坑。
刚换的 amd R7735HS 笔记本,8核16线程,32GB内存。性能得实强悍 。 当需要发布iOS版本时发现,我没有macos ,那就安装个vmware 吧。看了一下Apple 要求以后的发布的APP需要以xcode14.3或以后版本开发的版本,但xcode14.3…...
宝塔反代openai官方API接口详细教程,502 Bad Gateway问题解决
一、前言 宝塔反代openai官方API接口详细教程,实现国内使用ChatGPT502 Bad Gateway问题解决, 此方法最简单快捷,没有复杂步骤,不容易出错,即最简单,零代码、零部署的方法。 二、实现前提 一台海外VPS服务…...
【leetocde】128. 最长连续序列
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入:nums [100,4,200,1,3,2] 输出:4 …...
【Vue3】动态 class 类
如果你想在 Vue.js 中动态设置元素的 class 类名,你可以使用以下两种主要方式: 绑定一个动态的 class 对象:你可以使用 v-bind 或简写的 : 来绑定一个包含类名的对象,其中类名的键是类名字符串,值是一个布尔值或计算属…...
【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)
目录 RedisString(字符串)List(列表)Hash(字典)Set(集合)ZSet(有序集合) Redis Redis有5种基本的数据结构,分别为:string(字符串)、list(列表)、set(集合)、hash(哈希&a…...
ubuntu源码安装aria2
github:GitHub - aria2/aria2: aria2 is a lightweight multi-protocol & multi-source, cross platform download utility operated in command-line. It supports HTTP/HTTPS, FTP, SFTP, BitTorrent and Metalink. 发行说明:GitHub - aria2/aria2 at releas…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
