1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 日期时间编辑器(模拟QDateTimeEdit的自定义控件)——QML

日期时间编辑器(模拟QDateTimeEdit的自定义控件)——QML

时间:2024-04-01 18:24:44

相关推荐

日期时间编辑器(模拟QDateTimeEdit的自定义控件)——QML

前言

现在比较闲,我就把手上的项目写了两个版本:一版QtWidgets c++实现的;另一版 qml 加少量c++实现的(当然还没写完)。可能我用QtWidgets用习惯了,感觉qml少很多控件,然后很多东西需要自己写:我发现qml没有时间日期编辑器/选择器,所以我模仿了QDateTimeEdit,根据思路的不同写了两个版本。

代码和说明

QDateTimeEdit可以通过两种方式修改:一则是直接编辑修改;二呢,是通过按钮上下调。

为了直接修改,时间数据不会错,所以我加了验证器(validator)属性,这部分是通过c++ 继承QValidator实现的

//DateTimeValidator.h#ifndef DATETIMEVALIDATOR_H#define DATETIMEVALIDATOR_H#include <QValidator>#include<QDateTime>class DateTimeValidator : public QValidator{Q_OBJECTpublic:DateTimeValidator();State validate(QString& input, int& pos) const;};#endif // DATETIMEVALIDATOR_H

//DateTimeValidator.cpp#include "DateTimeValidator.h"DateTimeValidator::DateTimeValidator(){}QValidator::State DateTimeValidator::validate(QString &input, int &pos) const{QDateTime dt = QDateTime::fromString(input, "yyyy-MM-dd HH:mm");if (dt.isNull()) // If null, the input cannot be parsed{return QValidator::Invalid;}return QValidator::Acceptable;}

然后在main.cpp中注册此属性

qmlRegisterType<DateTimeValidator>("ponents", 1, 0, "DateTimeValidator");

纯字符串操作版本

qml没有关于日期时间的类,挨边的只有一个日历,但是不是我想要的。所以若想改变它的值——字符串,好像可以通过直接修改对应的字符实现,所以就有了这个版本:通过光标的位置,得知需要修改的部分(年/月/日/时/分),然后加减后,再拼成字符串写入就行了。注意:月、日、时和分他们的值可能是一位(即小于10),前面要加'0';还有大小月,闰年的区分。

这个版本和JS Date版本稍微有点不同:这个版本达到极限值后,就不响应了,比如若秒达到59后将不再响应加操作,一直停留在59(当然若你想59后面从0开始也可以,一句话的事儿)。而JS版本若达到极限值后再操作(加/减),将影响到上一位。

这个属于最初版本可能看着很繁琐,可以精简,而且存在着小bug,但是我懒,就先这样吧

import QtQuick 2.0import QtQuick.Controls 1.2import ponents 1.0TextField {id:dateEdit;text : "-07-30 00:00"inputMask: "9999-99-99 99:99"validator: DateTimeValidator {}Rectangle{id:upArrow;x:dateEdit.width-13; y:2;width: 9;height: (dateEdit.height-8)/2;color: "#00000000";Image{anchors.centerIn: parent;width: 9;height: 5;source: "qrc:/img/dateUp.png";}MouseArea{anchors.fill: parent;onPressed: upArrow.color="#cfcfcf";onReleased: upArrow.color="#00000000";onClicked:{var pos=dateEdit.cursorPosition;var txt=dateEdit.text;if(pos<4){//年份var year=txt.substr(0,4);year=parseInt(year);var other=txt.substr(4);txt=(year+1).toString().concat(other);}else if(pos>=4&&pos<=6){//月份var month=txt.substr(5,2)month=parseInt(month);if(month===12){return;}month=month+1;if(month<10)month=0+month.toString();elsemonth=month.toString();other=txt.substr(0,5);var other2=txt.substr(7);txt=other+month+other2;}else if(pos>=7&&pos<=9){//天数var day=txt.substr(8,2);month=parseInt(txt.substr(5,2));if(month===1||month===3||month===5||month===7||month===8||month===10||month===12){if(day==="31")return}else if(month===2){year=parseInt(txt.substr(0,4));if (year%100!=0&&year%4==0||year%400==0){//闰年if(day==="29")return;}else{//平年if(day==="28")return}} else{if(day==="30")return;}day=parseInt(day)+1;if(day<10)day=0+day.toString();elseday=day.toString();other=txt.substr(0,8);other2=txt.substr(10);txt=other+day+other2;}else if(pos>=10&&pos<=12){var hour=txt.substr(11,2);if(hour==="23")return;hour=parseInt(hour)+1;if(hour<10)hour=0+hour.toString();elsehour=hour.toString();other=txt.substr(0,11);other2=txt.substr(13);txt=other+hour+other2;}else{var min=txt.substr(14,2);if(min==="59")return;min=parseInt(min)+1;if(min<10)min=0+min.toString();elsemin=min.toString();other=txt.substr(0,14);txt=other+min;}dateEdit.text=txt;dateEdit.cursorPosition=pos;}}}Rectangle{id:downArrow;anchors.left: upArrow.left;anchors.top: upArrow.bottom;anchors.topMargin: 4;width: upArrow.width;height: upArrow.height;Image{anchors.centerIn: parent;width: 9;height: 5;source: "qrc:/img/dateDown.png";}MouseArea{anchors.fill: parent;onPressed: downArrow.color="#cfcfcf";onReleased: downArrow.color="#00000000";onClicked:{var pos=dateEdit.cursorPosition;var txt=dateEdit.text;if(pos<4){//年份var year=txt.substr(0,4);year=parseInt(year);var other=txt.substr(4);txt=(year-1).toString().concat(other);}else if(pos>=4&&pos<=6){//月份var month=txt.substr(5,2)month=parseInt(month);if(month===1){return;}month=month-1;if(month<10)month=0+month.toString();elsemonth=month.toString();other=txt.substr(0,5);var other2=txt.substr(7);txt=other+month+other2;}else if(pos>=7&&pos<=9){//天数var day=txt.substr(8,2);month=parseInt(txt.substr(5,2));if(day==="01")return;day=parseInt(day)-1;if(day<10)day=0+day.toString();elseday=day.toString();other=txt.substr(0,8);other2=txt.substr(10);txt=other+day+other2;}else if(pos>=10&&pos<=12){var hour=txt.substr(11,2);if(hour==="00")return;hour=parseInt(hour)-1;if(hour<10)hour=0+hour.toString();elsehour=hour.toString();other=txt.substr(0,11);other2=txt.substr(13);txt=other+hour+other2;}else{var min=txt.substr(14,2);if(min==="00")return;min=parseInt(min)-1;if(min<10)min=0+min.toString();elsemin=min.toString();other=txt.substr(0,14);txt=other+min;}dateEdit.text=txt;dateEdit.cursorPosition=pos;}}}}

JS Date版本

这个版本逻辑主要是靠JS Date实现的,说实话我不太会,所以我是对着教程敲的(附赠网络地址)。这个参考了一些网上的对Date的操作(Date转字符串,字符串转Date),整体逻辑比上一个清晰很多,看着也舒服优雅一些。

import QtQuick 2.0import QtQuick.Controls 1.2import ponents 1.0TextField {id:dateEdit;text : "-07-30 00:00"inputMask: "9999-99-99 99:99"validator: DateTimeValidator {}Rectangle{id:upArrow;x:dateEdit.width-13; y:2;width: 9;height: (dateEdit.height-8)/2;Image{anchors.centerIn: parent;width: 9;height: 5;source: "qrc:/img/dateUp.png";}MouseArea{anchors.fill: parent;onPressed: upArrow.color="#cfcfcf";onReleased: upArrow.color="#00000000";onClicked:{operateDateTime(1);}}}Rectangle{id:downArrow;anchors.left: upArrow.left;anchors.top: upArrow.bottom;anchors.topMargin: 4;width: upArrow.width;height: upArrow.height;Image{anchors.centerIn: parent;width: 9;height: 5;source: "qrc:/img/dateDown.png";}MouseArea{anchors.fill: parent;onPressed: downArrow.color="#cfcfcf";onReleased: downArrow.color="#00000000";onClicked:{operateDateTime(-1);}}}function operateDateTime(operate){var pos=dateEdit.cursorPosition;var txt=dateEdit.text;txt=txt+":00";var date=convertDateFromString(txt);var str=date.toString();if(pos<4){//年份date.setFullYear(date.getFullYear()+operate);}else if(pos>=4&&pos<=6){//月份date.setMonth(date.getMonth()+operate);}else if(pos>=7&&pos<=9){//天数date.setDate(date.getDate()+operate);}else if(pos>=10&&pos<=12){//小时date.setHours(date.getHours()+operate);}else{//分钟date.setMinutes(date.getMinutes()+operate);}str=date.toString();txt=dateFormat(date,"yyyy-MM-dd hh:mm");dateEdit.text=txt;dateEdit.cursorPosition=pos;}function checkNull(value) {return (!value || value == null || typeof(value) == "undefined" || value == "");}// 填充0function fillZero(value) {return value.toString().length < 2 ? ('0' + value) : value}//字符串转Datefunction convertDateFromString(dateString) {if (dateString) {var arr1 = dateString.split(" ");var sdate = arr1[0].split('-');var stime=arr1[1].split(':');var date = new Date(sdate[0], sdate[1]-1, sdate[2],stime[0],stime[1],stime[2]);return date;}}//Date通过格式str转为字符串function dateFormat(d, str) {var formatStr = checkNull(str) ? 'yyyy-MM-dd HH:mm:ss' : str;if (checkNull(d)) { // 如果日期为空,自动获取当前日期d = new Date();} else if (d.constructor != Date) { // 如果参数不是一个日期对象,就认为是一个标准Long值日期d = new Date(d);}return formatStr .replace("yyyy", d.getFullYear()).replace("MM", fillZero(d.getMonth() + 1)).replace("dd", fillZero(d.getDate())).replace("hh", fillZero(d.getHours())).replace("mm", fillZero(d.getMinutes())).replace("ss",fillZero(d.getSeconds())).replace("sss", d.getMilliseconds());}}

效果图

结束语

日期时间编辑器本来觉得挺简单的东西,结果折腾挺久,感觉想学好qml道阻且长啊!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。