基于 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…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)
错误一:yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因,后面把yaml.safe_dump直接替换成yaml.dump,确实能保存,但出现乱码: 放弃yaml.dump,又切…...

Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...
算法250609 高精度
加法 #include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; char input1[205]; char input2[205]; int main(){while(scanf("%s%s",input1,input2)!EOF){int a[205]…...
FTXUI::Dom 模块
DOM 模块定义了分层的 FTXUI::Element 树,可用于构建复杂的终端界面,支持响应终端尺寸变化。 namespace ftxui {...// 定义文档 定义布局盒子 Element document vbox({// 设置文本 设置加粗 设置文本颜色text("The window") | bold | color(…...

CMS内容管理系统的设计与实现:多站点模式的实现
在一套内容管理系统中,其实有很多站点,比如企业门户网站,产品手册,知识帮助手册等,因此会需要多个站点,甚至PC、mobile、ipad各有一个站点。 每个站点关联的有站点所在目录及所属的域名。 一、站点表设计…...
AWS vs 阿里云:功能、服务与性能对比指南
在云计算领域,Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商,各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5],我将从功能、服务和性能三个方面进行结构化对比分析&#…...