Qt组件库之类系统桌面图标功能完善

Qt组件库之类系统桌面图标功能完善上一篇文章中 我们已经实现了自定义图标 Item 和移动功能的实现 今天我们来继续完善该功能 包括图标 Item 下方的文本绘制 长文本换行和缩略 双击响应 位置自动匹配以及封装好的 简单的创建和布局方法

大家好,欢迎来到IT知识分享网。

Qt组件库之类系统桌面图标功能完善

前言

上一篇文章中,我们已经实现了自定义图标Item和移动功能的实现,今天我们来继续完善该功能,包括图标Item下方的文本绘制、长文本换行和缩略、双击响应、位置自动匹配以及封装好的、简单的创建和布局方法。先来看一下最终效果:

文本绘制和长文本缩略显示功能:

Qt组件库之类系统桌面图标功能完善

图标Item位置不再随意摆放,而是成行成列,自动匹配合适的位置:

Qt组件库之类系统桌面图标功能完善

图标Item双击响应:

Qt组件库之类系统桌面图标功能完善

每种功能的实现效果还是和Windows桌面上的图标很相似的,下面我们来看看各个功能具体的实现方法。

文本绘制和长文本处理

根据我自己对Windows桌面图标的试验,总结了以下几个图标下方文本绘制的原则:

  • 文本较长时可换行。
  • 图标未选中时,文本最多绘制两行,如果文本多于两行且图标并未选中时,则只显示一行文本。
  • 图标选中时,无论文本有多长,全部显示,并且选中时的背景也随文本的函数动态变化。

知道了基本的原则,那么我们就来逐步实现每个功能,首先不考虑换行的话,文字绘制其实很简单,只需要调用QPainter中的drawText方法即可实现如下:

painter->setPen(QColor(255, 255, 255)); painter->drawText(QRectF(0, 0, 40, 40), Qt::AlignHCenter, "文本");

文本可以绘制了以后,换行如何实现?其实Qt都帮我们处理好了,我们只需要在字符串需要换行的位置插入’\n’即可,例如:

painter->drawText(QRectF(0, 0, 40, 40), Qt::AlignHCenter, "Google \nChrome");

虽然这样换行是实现了,但是如果我们想绘制一段很长的文本,总不能还要自己先数好字数,然后再挨个插入’\n’,那多麻烦,使用起来太不人性化。于是我便写了个函数来实现该功能,即每隔10个字符,便插入一个换行符,文本长度限制在128个字符以内:

void IconWidget::calcTextLine() { //计算文字显示的行数,默认一行显示10个字符 m_nTextLen = strlen(m_strText.toLocal8Bit().data()); char szText[256] = { 0 };//最多显示128个字符,但是分配256 memcpy(szText, m_strText.toLocal8Bit().data(), (m_nTextLen > 128 ? 128 : m_nTextLen)); m_nTextLine = 0;//记录文本行数 for (int i=10; i<strlen(szText); i+=10) { memcpy(szText+i+1, szText+i, strlen(szText)-i); szText[i] = '\n'; i++; m_nTextLine++; } m_strText = QString::fromLocal8Bit(szText); }

现在文本换行功能也实现了,那么文本缩略不就更好实现了,就检测一下文本行数,如果函数大于2则只显示第一行文本,否则就全部显示。其实Windows中长文本缩略时有时会加上省略号,该功能我没实现,如果要想实现也方便,无非是替换第一行文本的最后几个字符为’.’即可。

if (m_nTextLine == 3) { char szOmit[11] = { 0 }; memcpy(szOmit, szText, 10); m_strText_Omit = QString::fromLocal8Bit(szOmit); }

文本绘制最后就只剩下图标Item选中和未选中时不同呈现效果的问题了。之前我们已经在paint函数中实现了选中状态的绘制,所以选中时的文本绘制我们也放在该函数中处理。其中需要注意的就是绘制区域的问题,因为文本行数不同时,如果你每次都绘制一个固定大小的区域,虽然横向不会有问题,但是垂直方向肯定会出现要么显示不全,要么出现空白的情况,因此我们需要将绘制区域的高度与文本行数关联起来。行数在上面的calcTextLine函数中已经得到,因此绘制区域的高度就可以轻松计算出来:

m_nBottomRightY_Pro = ICON_HEIGHT + m_nTextLine * LINE_HEIGHT; //每多一行文字就多加LINE_HEIGHT的高度

注意,此时我们产生了两个绘制区域的高度,一个是未选中时的高度m_nBottomRightY,一个是选中时的高度m_nBottomRightY_Pro,这两个参数可能相等也肯能不等,完全取决于文本行数是否大于2行。但是此时我们的boundingRect()函数就需要作出修改,需要使用两者当中更高的那个高度m_nBottomRightY_Pro,否则就会因绘制区域不同,产出如下图所示的问题:

Qt组件库之类系统桌面图标功能完善

位置自动匹配

我们在Windows桌面上进行图标拖动时,无论我们在什么地方松开鼠标,图标都会自动与对应的行和列对齐,因此桌面不会显得很杂乱。之间我们自己实现的图标Item拖到哪就放置在哪,很不好看,不以规矩不成方圆,因此,我决定给其立个“规矩”。

我们知道,图标It最后停靠的位置是由鼠标释放时的位置决定的,因此我们要重写mouseReleaseEvent函数。然后在该函数中获取鼠标在Scene中的位置坐标,根据坐标和我们图标Item的摆放间隔,就可以计算出图标Item应该放置的位置,具体实现如下:

//鼠标释放响应 void IconWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { //根据鼠标在scene中的位置,计算出Item应该在的行和列 //每行20个Item,也可以根据Scene的宽度和间隙计算出个数 int xPos = event->scenePos().x(); int yPos = event->scenePos().y(); //qDebug() << xPos << ", " << yPos; int nRow = xPos / ICON_GAP; int nColumn = yPos / ICON_GAP; //qDebug() << "Row = " << nRow << ", Column = " << nColumn; this->setPos(nRow * ICON_GAP + SCENE_SHIFTING, nColumn * ICON_GAP + SCENE_SHIFTING); //update(); //因为上面setPos了,所以不需要手动update了 QGraphicsItem::mouseReleaseEvent(event); }

图标双击响应

系统桌面上的图标双击都是能打开对应的程序或文件的,而我们后面也需要双击图标Item预览对应的组件,因此我们需要实现图标Item的双击响应,当前我只是在Item被双击时弹出一个QMessageBox:

//鼠标双击响应 void IconWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { if(event->button() == Qt::LeftButton) QMessageBox::information(NULL, "J_Component", m_strText); }

创建和自动布局功能封装

上一篇中由于时间问题,演示的时候创建自定义图标Item我用的是数组,而且创建和布局也不方便,因此趁着今天周末也对该问题进行了优化,封装了如下的方法进行图标Item的创建和在Scene中的自动布局:

//创建并添加自定义图标Item到Scene中 void Widget::addIconWidgetToScene(QString strImagePath, QString strText) { IconWidget *pIconWidget = new IconWidget(strImagePath, strText); m_pScene->addItem(pIconWidget); //每行20个Item int nRow = m_pIconWidgetVector.count() % 20; int nColumn = m_pIconWidgetVector.count() / 20; pIconWidget->setPos(nRow * ICON_GAP + SCENE_SHIFTING, nColumn * ICON_GAP + SCENE_SHIFTING); m_pIconWidgetVector.append(pIconWidget); }

这里我使用了容器存放动态创建的IconWidget对象,在窗口析构时进行内存的释放:

for (int i=0; i<m_pIconWidgetVector.count(); i++) { delete m_pIconWidgetVector[i]; m_pIconWidgetVector[i] = NULL; }

因此创建图标Item就变得非常的简单:

addIconWidgetToScene(":/Images/.png", ""); addIconWidgetToScene(":/Images/WeChat.png", "微信"); addIconWidgetToScene(":/Images/QT.png", "Qt Creator"); addIconWidgetToScene(":/Images/Emoji.png", "0.test"); addIconWidgetToScene(":/Images/Chrome.png", "Google Chrome"); addIconWidgetToScene(":/Images/Computer.png", "我的电脑"); addIconWidgetToScene(":/Images/TaoBao.png", "淘宝"); addIconWidgetToScene(":/Images/ZhiFuBao.png", "支付宝"); for (int i=0; i<100; i++) addIconWidgetToScene(":/Images/Baidu.png", "百度");

运行效果如下:

Qt组件库之类系统桌面图标功能完善

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/159698.html

(0)
上一篇 2024-11-30 08:45
下一篇 2024-11-30 09:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信