临汾山东漯河饰品美体美文
投稿投诉
美文创意
爱情通信
用品婚姻
爱好看病
美体软件
影音星座
瑜伽周边
星座办公
饰品塑形
搞笑减肥
幼儿两性
智家潮品
漯河衢州
兴义眉山
桂林阳泉
玉溪简阳
山东遂宁
永城新余
梧州洛阳
泸州温州
临汾清远
营口常熟
浙江大连
桐乡宜昌

自定义日历(一)

9月17日 飞虹谷投稿
  1、概要
  最近一直比较忙,根本没时间记录自己想写的东西,趁着国庆小长假,我自己也列出了想记录的一些小东西,方便他人借鉴,也方便我自己学习。废话不多说,我先来贴上我自己的demo展示图,这个demo比较复杂,我可能会分两篇博客来讲述。与其说是因为demo复杂,还不如说是这个月份是按照完全不同的两种思路来展示。
  月份展示效果
  如上图所示,这是两种日历展示形式,上方的日历是用label拼成,下方的日历是用一个窗口绘制而成,完全不同的两种路线,各有优缺点。接下来我将会分别介绍这两种月份的实现过程。2、优缺点比较
  这两种日历的优缺点我总结了一个简单的表格,如下表:
  label平凑
  widget自绘
  优点实现思路简单容易理解,每天都是一个label
  绘制不同于其他天比较方便(蓝点)实现稍微复杂,每天的位置需要自己计算
  相对于第一种相率高,内存占用率低,事件处理层级少
  窗口放大缩小效率高
  背景色渐变容易实现
  缺点每天都是一个label,对性能有影响
  窗口大小变化时麻烦
  背景色渐变难以实现
  widget每次整个重绘,每一天上的内容绘制比较难以计算
  两种月份优缺点比较
  本片文字我重点介绍下第二种日历的绘制,也就是整个窗口重新绘制,这种日历的实现难点就在于窗口事件的处理上,设计了好的数据结构,我们的程序处理才会变得简单。3、数据结构设计1structtDayFlag2{3signedcharmchFlagM;1pre0cur1next4unsignedshortmchFlagD;daynum5};
  这个结构负责存储每一天的信息,mchFlagM这个字段表示是否是当前月份的,1:上一个月,1:下一个月,0表示当前月份;mchFlagD存储是一个月中的那一天。
  接下来是一个impl接口类DrawDateTimePrivate,这个类中存储了大量的计算信息,负责日历的数据计算和比较1structDrawDateTime::DrawDateTimePrivate2{3public:4DrawDateTimePrivate(DrawDateTimes)5:mSelf(s)6,mpOnChanged(NULL)7{8maRectnewQRect〔mcolumncountmrowcount〕;9maDayFlagnewtDayFlag〔mcolumncountmrowcount〕;10msOverIndex1;1112SYSTEMTIME13GetLocalTime(st);14mwYearst。wY15mwMonthst。wM16mwDayst。wD17}1819DrawDateTimePrivate()20{21delete〔〕maR22delete〔〕maDayF23}2425public:26unsignedintGetColumnLeft(intcolumn)27{28unsignedintleft(widthleftBorderrightBordercolumnSpace)mcolumncountcolumnleftB293031}3233unsignedintGetColumnRight(intcolumn)34{35if(column0columnmcolumncount)36{37column0;38}3940总宽度左border由border(mcolumncount1)列间隙41unsignedintitemWidth(widthleftBorderrightBorder(mcolumncount1)columnSpace)42unsignedintrightGetColumnLeft(column)itemW434445}4647unsignedintGetRowTop(introw)48{49QFontMetricsfm(weekFont);50intweekHeightfm。height();5152unsignedinttop(heighttopBorderbottomBorderweekHeightrowSpace)mrowcountrow53spaceweekH545556}5758unsignedintGetRowBottom(introw)59{60if(row0rowmrowcount)61{62row0;63}6465QFontMetricsfm(weekFont);66intweekHeightfm。height();6768总高度上border下border(mrowcount1)行间隙week高69unsignedintitemHeight(heighttopBorderbottomBorderweekHeightspace(mrowcount1)rowSpace)70unsignedintbottomGetRowTop(row)itemH717273}7475public:76intcolumnSpace5;77introwSpace5;7879intleftBorder10;80intrightBorder10;81inttopBorder5;82intbottomBorder5;8384intwidth100;85intheight80;8687intspace10;周名称和天之间距离8889intmcolumncount7;列数90intmrowcount6;行数9192QFontweekFontQFont(STR(微软雅黑,14));93QFontdayF9495public:96DrawDateTimemS9798IDateInfoChangedNotifympOnC99100unsignedshortmwY101unsignedshortmwM102unsignedshortmwD103104tDayFlagmaDayF各个按钮日期号105QRectmaR各个按钮区域106shortmsOverI热点按钮下标107108boolMatchRealDate(tDayFlagdf)109{110if(df。mchFlagDmwDay0df。mchFlagM)111{112113}114115}116117重置当前月份上的日期flag及显示的数据118voidResetDayFlag()119{120unsignedshortpreY,preM;121GetPreviousMonth(preY,preM);122123intnPreMonDaysDayofMonth(preY,preM);124intnCurMonDaysDayofMonth(mwYear,mwMonth);125intweekCalDayofWeek(mwYear,mwMonth,1);126127intindex0;128129for(inti0;i,index)130{131maDayFlag〔index〕。mchFlagM1;132maDayFlag〔index〕。mchFlagD(nPreMonDaysweek1)i;133}134135for(inti0;inCurMonDi,index)136{137maDayFlag〔index〕。mchFlagM0;138maDayFlag〔index〕。mchFlagDi1;139}140141mrowcountindex7(index70?0:1);142143for(intj1;j,index)144{145maDayFlag〔index〕。mchFlagM1;146maDayFlag〔index〕。mchFlagDj;147}148}149150获取上一个月的年和月份151voidGetPreviousMonth(unsignedshortpreYear,unsignedshortpreMonth)152{153if(mwMonth1)154{155preYearmwY156preMonthmwMonth1;157}158else159{160preYearmwYear1;161preMonth12;162}163}164165获取下一个月的年和月份166voidGetNextMonth(unsignedshortnextYear,unsignedshortnextMonth)167{168if(mwMonth12)169{170nextYearmwYear1;171nextMonth1;172}173else174{175nextYearmwY176nextMonthmwMonth1;177}178}179};GetColumnLeft:获取指定列的左边界GetColumnRight:获取指定列的右边界GetRowTop:获取指定行的上边界GetRowBottom:获取指定行的下边界MatchRealDate:检测给定日期是否是当前天ResetDayFlag:重置impl中的内存数据GetPreviousMonth:获取上一个月份的年和日GetNextMonth:获取下一个月份的年和日4、区域生成
  区域生成顾名思义就是生成日期的绘制区域,这个需要根据当前窗口的大小、列间距、行间距等信息来计算每一天的矩形区域,当有月份切换时需要重新计算该信息,如果觉着这个过程对性能没有影响可以在每次整个绘制的时候都重新计算,这样有助于程序在出错时自动恢复。关于区域自动生成,在上一个小节我们已经给出了接口解释,接下来我将贴出实现代码,并做相应解释1重置当前月份上的日期flag及显示的数据2voidResetDayFlag()3{4unsignedshortpreY,preM;5GetPreviousMonth(preY,preM);67intnPreMonDaysDayofMonth(preY,preM);8intnCurMonDaysDayofMonth(mwYear,mwMonth);9intweekCalDayofWeek(mwYear,mwMonth,1);1011intindex0;1213for(inti0;i,index)重置上一个月份的日期14{15maDayFlag〔index〕。mchFlagM1;16maDayFlag〔index〕。mchFlagD(nPreMonDaysweek1)i;17}1819for(inti0;inCurMonDi,index)重置本月份的日期20{21maDayFlag〔index〕。mchFlagM0;22maDayFlag〔index〕。mchFlagDi1;23}2425mrowcountindex7(index70?0:1);更新行数2627for(intj1;j,index)重置下一个月份的日期28{29maDayFlag〔index〕。mchFlagM1;30maDayFlag〔index〕。mchFlagDj;31}32}5、点击位置是哪一天
  在自绘制日历的时候,点击位置或者hover位置是哪一个日期判断是非常重要的,这个涉及到整个日历是否是有一个友好的交互。在开始做这个基于widget绘制日的时候我也迷茫过,觉得判断点击位置是哪一天非常困难,实时也是这样的,判断起来是非常困难的,直到后来我看到了一个网友的数据结构设计,原来这个判断是如此的简单,不过简单的判断都是基于一个优秀的结构设计,判断代码如下:1intDrawDateTime::GetIndex(constQPointpoint)2{3intid1;4for(inti0;iptrmrowcountptrmcolumncount4;i)5{6QRectrcptrmaRect〔i〕;7if(point。x()rc。left()point。x()rc。right()8point。y()rc。top()point。y()rc。bottom())9{101112}13}141516}
  上述判断只用了一个循环就可以判断出点击位置是在那个日期上,ptrmaRect这个结构存储了所有日期的矩形区域,他在合适的时机就会重置。6、周内容绘制1voidDrawDateTime::DrawWeek(QPainterpainter)2{3QStringaText〔7〕{STR(周日),STR(周一),STR(周二),STR(周三),STR(周四),STR(周五),STR(周六)};45painter。save();6painter。setFont(ptrweekFont);7QFontMetricsfm(ptrweekFont);8intheightfm。height();9for(inti0;i7;i)10{11intleftptrGetColumnLeft(i);12intrightptrGetColumnRight(i);13QRectrect(left,ptrtopBorder,rightleft,height);14painter。drawRect(rect);15painter。drawText(rect,Qt::AlignCenter,aText〔i〕);16}17painter。restore();18}7、日期内容绘制1voidDrawDateTime::DrawDay(QPainterpainter)2{3ptrResetDayFlag();45painter。save();67QFontMetricsfm(ptrweekFont);8intweekHeightfm。height();910for(intcolumn0;column)11{12intcolumnleftptrGetColumnLeft(column);13intcolumnrightptrGetColumnRight(column);14for(introw0;row)15{1617QRectrcTmpptrmaRect〔index〕;18tDayFlagflagptrmaDayFlag〔index〕;1920rcTmp。setLeft(columnleft);21rcTmp。setRight(columnright);22rcTmp。setTop(ptrGetRowTop(row));23rcTmp。setBottom(ptrGetRowBottom(row));2425QPainterP26path。addRoundRect(rcTmp,25);2728if(indexptrmsOverIndex)hover时背景色29{30painter。fillPath(path,QColor(144,151,151));31}3233painter。save();34if(1flag。mchFlagM1flag。mchFlagM)35{36painter。setPen(QColor(Qt::blue));37}38else39{40if(ptrMatchRealDate(flag))41{42painter。setPen(QColor(Qt::red));43}44elseif(indexptrmsOverIndex)45{46painter。setPen(QColor(Qt::white));47}48else49{5051}52}53painter。setOpacity(0。5);绘制半透明度字54painter。drawText(rcTmp,Qt::AlignCenter,QString::number(flag。mchFlagD));5556painter。restore();5758painter。drawPath(path);59}60}6162painter。restore();63}8、月份切换1voidDrawDateTime::PreviousMonth()上一个月份2{3unsignedshortyear,4ptrGetPreviousMonth(year,month);56intacturlDaysDayofMonth(year,month);7if(acturlDaysptrmwDay)8{9ptrmwDayacturlD10}11SetDate(year,month,ptrmwDay);1213update();14}1516voidDrawDateTime::NextMonth()下一个月份17{18unsignedshortyear,19ptrGetNextMonth(year,month);2021intacturlDaysDayofMonth(year,month);22if(acturlDaysptrmwDay)23{24ptrmwDayacturlD25}26SetDate(year,month,ptrmwDay);2728update();29}9、日期点击时效果1voidDrawDateTime::mousePressEvent(QMouseEventevent)2{3if(eventbutton()Qt::LeftButton)4{5intcurGetIndex(eventpos());6tDayFlagflagptrmaDayFlag〔cur〕;78unsignedshortyearptrmwYear,monthptrmwM9if(flag。mchFlagM1)10{11ptrGetPreviousMonth(year,month);12}13elseif(flag。mchFlagM1)14{15ptrGetNextMonth(year,month);1617}18boolb(ptrmwDay!flag。mchFlagDmonth!ptrmwMonthyear!ptrmwYear);19if(b)20{21ptrmwDayflag。mchFlagD;22ptrmwM23ptrmwY24update();25}26}27}
  日期点击时,如果点击的是上一个月份的日期,则把当前月份切换到上一个月;如果点击的是下一个月的日期,则把当前月份切换到下一个月;否则当前月份不变,当前点击的日期颜色变成白色。10、鼠标移动时效果1voidDrawDateTime::mouseMoveEvent(QMouseEventevent)2{3intcurGetIndex(eventpos());4boolb(cur!ptrmsOverIndex);5if(b)6{7intpreviousHoverptrmsOverI8ptrmsOverI9update(ptrmaRect〔cur〕);10update(ptrmaRect〔previousHover〕);11}1213QWidget::mouseMoveEvent(event);14}
  鼠标hover时,修改当前所hover的日期,然后在重新绘制时,如果是hover的日期,则绘制颜色变为QColor(144,151,151)
  点击领取Qt学习资料视频教程链接
  11、实现动画
  本文所讲述的这种日历在demo中实现时没有使用动画来切换月份,但是用label拼凑的日历使用了动画来切换月份,如果有兴趣的同学可以把本文后面提供的demo下载下来,自行进行修改,修改的时候可以参考label拼凑月份的动画,由于label拼凑的月份实现起来更为繁琐,因此本片文章就不继续讲解了,在下一篇文章中我将讲解一些关键的实现思路和不足。顺便提一句,支持动画切换月份的日历控件时在一个窗口的基础上切换的,感兴趣的同学也可以实现5个月份的切换,就像一些音乐播放器主页上的音乐提示一样,是一个轮播的形式。例如网易音乐
  网易轮播
  日历同意可以以这样的形式来切换,这样的功能我已经实现了,如果感兴趣的同学可以私聊,demo中的代码在完善优化下,就可以做出这个效果,基于widget完全绘制的日历可能更合适这样的切换,label的堆砌在切换的时候可能会有效率的问题,这就取决于你的机器了,一般的机器还都是没有问题的,除非你要做对效率要求很高的程序。
  关于label拼凑的日历我将会在自定义日历(二)给出详细讲解
  作者:朝十晚八orTwowords
  转载:https:www。cnblogs。comswarmbeesp5927823。html
投诉 评论

圣保罗当地医院贝利的身体情况已有改善,将继续住院直播吧12月3日讯今日,圣保罗当地医院发表声明,贝利的身体状况已有改善,将继续住院治疗。医院发表的公告称:贝利的身体反应令人满意,目前贝利已经入住了普通病房,情况稳定,贝……面试官介绍一下Redis三种集群模式小码今天去面试。面试官:给我介绍一下Redis集群,小码:啊,平时开发用的都是单机Redis,没怎么用过集群了。面试官:好的,出门右转不谢。小码内心困惑……闲鱼卖二手,破财难消灾出品创业最前线作者冯羽编辑蛋总美编唐唐闲鱼再无新故事。当年,谌伟业在阿里茶水间头脑风暴,淘宝二手更名为闲鱼,将闲置经济、社区文化和互动社交织成一个……CES2023新风向新型显示技术争锋车载应用兴旺车窗透明显示、8K激光电视、8K印刷OLED、轻薄VR一体机美国当地时间1月5日在拉斯维加斯开幕的CES(国际消费类电子产品展)上,透露出显示技术的新风向。在2023全球……自定义日历(一)1、概要最近一直比较忙,根本没时间记录自己想写的东西,趁着国庆小长假,我自己也列出了想记录的一些小东西,方便他人借鉴,也方便我自己学习。废话不多说,我先来贴上我自己的de……卡塔尔世界杯澳大利亚队主帅梅西是史上最佳之一为袋鼠军团自豪新华社多哈12月3日电(记者肖亚卓、张逸飞)在3日的一场卡塔尔世界杯八分之一决赛中,澳大利亚队1:2不敌夺冠热门阿根廷队,澳大利亚队主教练阿诺德赛后盛赞阿根廷队球星梅西,称其为……重庆规矩最多牛肉店,要吃先买3瓶酒水,不守规矩不接待【大东哥的小日子】专注为您提供美食资讯您呐,一定想不到,重庆有一家规矩巨多的家庭小馆子,客人去吃饭直喊受气,还要被强制消费,却生意特别火爆,去吃的还大多数是本地人,而且不……微博杯2022年赛事回顾,携手各方探索电竞商业新赛道机遇与挑战,是近年来国内电竞产业发展的关键词。在新的时代背景下,各大电竞赛事都在主动寻求更高效的创新形式,从商业合作、大众赛事布局、商业化合作模式探索、电竞IP深度覆盖等领域着……孩子是不是正常发育?不用慌!这份发育里程碑清单一定要收好写文章越多,越深深感觉到,现在妈妈们太焦虑了!孩子有一点异常,就担心:是不是有病啊?是不是发育跟不上啊?然后妈妈们就到网上搜,我家宝宝这样正常吗。或者到处问别人,你……慕田峪长城旅游线路全攻略,游慕田峪必看一、【慕田峪介绍】二、【慕田峪长城旅游线路全攻略】三、【慕田峪长城怎么去】四、【慕田峪长城旅游注意事项】慕田峪长城以它悠远的历史,璀璨的文明,扬名中外。……冯小刚徐帆夫妇移民美国热争议,豪宅聚会显洒脱娱评大赏无娱乐,不热议。近日,杭州日报抖音号推送的一则关于冯小刚徐帆夫妇移民美国并在豪宅聚会的信息引发了热议,目前评论已经高达1。5万条。据相关网络媒介报道,……约旦之约(05)中东庞贝,千柱之城,罗马之外的罗马杰拉什杰拉什,位于安曼以北40公里,存世最完好的罗马古城之一,公元前63年罗马帝国占领此地,古城渐成规模,鼎盛时期,这里是德卡波利斯十城联盟重要成员,罗马帝国在东方最显耀的都市。……
美专家中美技术脱钩压力加大黄金价格多少钱一克?黄金回收是多少钱一克?2021年12月1房地产行业进入煎熬期MSCI中国A50成份股大全,有搞股票的朋友可以收藏研究明天能抄底吗?(纯干货)中国未售房屋库存创五年来新高,三四线城市成重灾区中国工商银行中国农业银行发布重要公告!事关这些消息期货中的股指期货波动1点就是300元,这么高的盈利为什么很少市场重要资讯A股二月容易红,统一电力市场体系机会是跌出的2021胡润全球白手起家女富豪榜发布中国占三分之二世茂股份聘任蔡柳为证券事务代表披露新租赁准则会计影响长得高但是腿短的女生怎么穿搭?光芒燃气热水器如何光芒燃气热水器的优势介绍详解浅析职校艺术设计教学思路的论文华为p10和p10plus哪个好华为p10和p10plus区溥仪结婚的时候那些军阀头子们都送了多少钱的礼金?徐世昌太阳的自述梦幻西游手游坐骑有何写Python需要养成的9个编程好习惯王者荣耀亚瑟六神装微信能查删掉的聊天记录吗(微信删除的记录去哪里找回来)老人糖尿病吃什么主食好任思绪飞

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找