当前位置: 首页 > news >正文

基于 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&#xff0c; pro 配置文件添加 sql 模块&#xff0c;需要用到 sqlite&#xff0c; 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是一种常用的计算机视觉图形检验方法&#xff0c;霍夫变换一…...

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&#xff08;但括号较少且没有分号&#xff09;&#xff0c;结构类似Oberon-2编译为本机代码&#xff08;没有JVM&#xff09;没有类&#xff0c;但有带有方法的结构接口没有实现继承。不过有type嵌入。函数是一等公民函数可以返…...

Grander因果检验(格兰杰)原理+操作+解释

笔记来源&#xff1a; 1.【传送门】 2.【传送门】 前沿原理介绍 Grander因果检验是一种分析时间序列数据因果关系的方法。 基本思想在于&#xff0c;在控制Y的滞后项 (过去值) 的情况下&#xff0c;如果X的滞后项仍然有助于解释Y的当期值的变动&#xff0c;则认为 X对 Y产生…...

Python-Flask:编写自动化连接demo脚本:v1.0.0

主函数&#xff1a; # _*_ 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依赖即可&#xff1a; <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka_2.13</artifactId><version>3.4.0</version></depend…...

Apache Doris 行列转换可以这样玩

行列转换在做报表分析时还是经常会遇到的&#xff0c;今天就说一下如何实现行列转换吧。 行列转换就是如下图所示两种展示形式的互相转换 1. 行转列 我们来看一个简单的例子&#xff0c;我们要把下面这个表的数据&#xff0c;转换成图二的样式 image-20230914151818953.png …...

【Qt图形视图框架】自定义QGraphicsItem和QGraphicsView,实现鼠标(移动、缩放)及键盘事件、右键事件

自定义QGraphicsItem和QGraphicsView 说明示例myitem.hmyitem.cppmyview.hmyview.cpp调用main.cpp 效果 说明 在使用Qt的图形视图框架实现功能时&#xff0c;一般会在其基础上进行自定义功能实现。 如&#xff1a;滚轮对场景的缩放&#xff0c;鼠标拖动场景中的项&#xff0c;…...

C语言结构体指针学习

结构体变量存放内存中&#xff0c;也有起始地址&#xff0c;定义一个变量来存放这个地址&#xff0c;那这个变量就是结构体指针&#xff1b; typedef struct mydata{int a1;int a2;int a3; }mydata;void CJgtzzView::OnDraw(CDC* pDC) {CJgtzzDoc* pDoc GetDocument();ASSERT…...

华为云云耀云服务器L实例评测|部署在线轻量级备忘录 memos

华为云云耀云服务器L实例评测&#xff5c;部署在线轻量级备忘录 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:电脑驱动更新工具的利器还是多余的软件?

亲爱的读者朋友们&#xff0c;你是不是经常为电脑的驱动问题而烦恼&#xff1f;如果是的话&#xff0c;你可能会对这款软件——Avast Driver Updater 电脑驱动更新工具感兴趣。但在你决定尝试之前&#xff0c;不妨先和我一起深入探讨一下它的优点、缺点以及它适用的使用场景。 …...

大数据Flink(九十五):DML:Window TopN

文章目录 DML:Window TopN DML:Window TopN Window TopN 定义(支持 Streaming):Window TopN 是一种特殊的 TopN,它的返回结果是每一个窗口内的 N 个最小值或者最大值。 应用场景...

使用OKHttpClient访问网络

使用OKHttpClient前要引入依赖&#xff1a; 在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&#xff08;同步…...

maui 开发AMD CPU踩的坑。

刚换的 amd R7735HS 笔记本&#xff0c;8核16线程&#xff0c;32GB内存。性能得实强悍 。 当需要发布iOS版本时发现&#xff0c;我没有macos &#xff0c;那就安装个vmware 吧。看了一下Apple 要求以后的发布的APP需要以xcode14.3或以后版本开发的版本&#xff0c;但xcode14.3…...

宝塔反代openai官方API接口详细教程,502 Bad Gateway问题解决

一、前言 宝塔反代openai官方API接口详细教程&#xff0c;实现国内使用ChatGPT502 Bad Gateway问题解决&#xff0c; 此方法最简单快捷&#xff0c;没有复杂步骤&#xff0c;不容易出错&#xff0c;即最简单&#xff0c;零代码、零部署的方法。 二、实现前提 一台海外VPS服务…...

【leetocde】128. 最长连续序列

给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&#xff1a;4 …...

【Vue3】动态 class 类

如果你想在 Vue.js 中动态设置元素的 class 类名&#xff0c;你可以使用以下两种主要方式&#xff1a; 绑定一个动态的 class 对象&#xff1a;你可以使用 v-bind 或简写的 : 来绑定一个包含类名的对象&#xff0c;其中类名的键是类名字符串&#xff0c;值是一个布尔值或计算属…...

【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)

目录 RedisString(字符串)List(列表)Hash(字典)Set(集合)ZSet(有序集合) Redis Redis有5种基本的数据结构&#xff0c;分别为&#xff1a;string&#xff08;字符串&#xff09;、list&#xff08;列表&#xff09;、set&#xff08;集合&#xff09;、hash&#xff08;哈希&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. 发行说明&#xff1a;GitHub - aria2/aria2 at releas…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...

规则与人性的天平——由高考迟到事件引发的思考

当那位身着校服的考生在考场关闭1分钟后狂奔而至&#xff0c;他涨红的脸上写满绝望。铁门内秒针划过的弧度&#xff0c;成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定"&#xff0c;构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...

云原生安全实战:API网关Envoy的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口&#xff0c;负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...

Element-Plus:popconfirm与tooltip一起使用不生效?

你们好&#xff0c;我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip&#xff0c;产品要求是两个需要结合一起使用&#xff0c;也就是鼠标悬浮上去有提示文字&#xff0c;并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...