冰箱贴类:

#include "draglabel.h"
#include <QtWidgets>DragLabel::DragLabel(const QString &text, QWidget *parent): QLabel(parent)
{QFontMetrics metric(font());QSize size = metric.size(Qt::TextSingleLine, text);QImage image(size.width() + 12, size.height() + 12, QImage::Format_ARGB32_Premultiplied);image.fill(qRgba(0, 0, 0, 0));QLinearGradient gradient(0, 0, 0, image.height()-1);gradient.setColorAt(0.0, Qt::white);gradient.setColorAt(0.2, QColor(200, 200, 255));gradient.setColorAt(0.8, QColor(200, 200, 255));gradient.setColorAt(1.0, QColor(127, 127, 200));QPainter painter(&image);painter.setRenderHint(QPainter::Antialiasing);painter.setBrush(gradient);painter.drawRoundedRect(QRectF(0.5, 0.5, image.width()-1, image.height()-1),25, 25, Qt::RelativeSize);painter.setFont(font());painter.setBrush(Qt::black);painter.drawText(QRect(QPoint(6, 6), size), Qt::AlignCenter, text);setPixmap(QPixmap::fromImage(image));m_labelText = text;
}QString DragLabel::labelText() const
{return m_labelText;
}

一个自定义的 QLabel,根据创建时传入的文本设确定一个图片的尺寸,使用渐变的画刷在图片绘制一个圆角矩形和文本,然后设置标签显示此图片。

然后是一个白色的窗口:

DragWidget::DragWidget(QWidget *parent): QWidget(parent)
{QFile dictionaryFile(QStringLiteral(":/dictionary/words.txt"));dictionaryFile.open(QFile::ReadOnly);QTextStream inputStream(&dictionaryFile);int x = 5;int y = 5;while (!inputStream.atEnd()){QString word;inputStream >> word;if (!word.isEmpty()){DragLabel *wordLabel = new DragLabel(word, this);wordLabel->move(x, y);wordLabel->show();wordLabel->setAttribute(Qt::WA_DeleteOnClose);x += wordLabel->width() + 2;if (x >= 245){x = 5;y += wordLabel->height() + 2;}}}QPalette newPalette = palette();newPalette.setColor(QPalette::Window, Qt::white);setPalette(newPalette);setMinimumSize(400, qMax(200, y));setWindowTitle(tr("Fridge Magnets"));setAcceptDrops(true);
}

从一个文本文件中读取内容:

每次读取一行,读取一行就创建一个冰箱贴并移动到相应的位置。最后设置窗口支持拖放。

鼠标按下的操作:

void DragWidget::mousePressEvent(QMouseEvent *event)
{DragLabel *child = static_cast<DragLabel*>(childAt(event->position().toPoint()));if (!child)return;QPoint hotSpot = event->position().toPoint() - child->pos();//鼠标按在child上的位置QByteArray itemData;QDataStream dataStream(&itemData, QIODevice::WriteOnly);dataStream << child->labelText() << QPoint(hotSpot);QMimeData *mimeData = new QMimeData;mimeData->setData(fridgetMagnetsMimeType(), itemData);mimeData->setText(child->labelText());QDrag *drag = new QDrag(this);drag->setMimeData(mimeData);drag->setPixmap(child->pixmap());drag->setHotSpot(hotSpot);child->hide();if (drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::CopyAction) == Qt::MoveAction)child->close();elsechild->show();
}

这里定义了一种自定义MIME类型:

static inline QString fridgetMagnetsMimeType() { return QStringLiteral("application/x-fridgemagnet"); }

内联的非成员函数,这种写法值得学习。

其中包含了了冰箱贴的文本和鼠标按下的位置。

开始拖放操作后,如果是拖放移到那么冰箱贴就隐藏了,拖动过程中显示的只是 QDrag::pixmap()。

拖动进入事件和拖动移到事件:

void DragWidget::dragEnterEvent(QDragEnterEvent *event)
{if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())){if (children().contains(event->source())){event->setDropAction(Qt::MoveAction);event->accept();}else{event->acceptProposedAction();}}else if (event->mimeData()->hasText()){event->acceptProposedAction();}else{event->ignore();}
}void DragWidget::dragMoveEvent(QDragMoveEvent *event)
{if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())){if (children().contains(event->source())){event->setDropAction(Qt::MoveAction);event->accept();}else{event->acceptProposedAction();}}else if (event->mimeData()->hasText()){event->acceptProposedAction();}else{event->ignore();}
}

这两个没啥好说的,主要是拖动放下事件:

void DragWidget::dropEvent(QDropEvent *event)
{if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())){const QMimeData *mime = event->mimeData();QByteArray itemData = mime->data(fridgetMagnetsMimeType());QDataStream dataStream(&itemData, QIODevice::ReadOnly);QString text;QPoint offset;dataStream >> text >> offset;DragLabel *newLabel = new DragLabel(text, this);newLabel->move(event->position().toPoint() - offset);newLabel->show();newLabel->setAttribute(Qt::WA_DeleteOnClose);if (event->source() == this){event->setDropAction(Qt::MoveAction);event->accept();}else{event->acceptProposedAction();}}else if (event->mimeData()->hasText()){QStringList pieces = event->mimeData()->text().split(QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts);QPoint position = event->position().toPoint();for (const QString &piece : pieces){DragLabel *newLabel = new DragLabel(piece, this);newLabel->move(position);newLabel->show();newLabel->setAttribute(Qt::WA_DeleteOnClose);position += QPoint(newLabel->width(), 0);}event->acceptProposedAction();}else{event->ignore();}
}

第一个分支在拖动放下的位置新建冰箱贴,从 QMimeData 取出数据设置其文本和位置。

第二个分支指示拖动能用空白符分割的文本到当前窗口,则使用其文本创建冰箱贴。

涉及到的类:

  • QFontMetrics
  • QLabel
  • QFile
  • QTextStream
  • QMimeData
  • QDataStream
  • QDrag

Qt官方示例:Fridge Magnets Example(冰箱贴)相关推荐

  1. Qt 官方示例 | 这几个 QML 版的 Hello World 你学会了吗?

    .我是老吴,一枚光荣的嵌入式底层劳动人民. 作为一名 C++ 手残党的我,又来分享 Qt 的学习心得啦. 学习 Qt 的最佳途径是阅读官方的手册和示例, 今天要分享的是 Qt 官方提供的几个 Qt Q ...

  2. Qt官方示例:UI Components: Dial Control Example

    这个示例演示了一个简单的自定义仪表盘组件. import QtQuick 2.2 import QtQuick.Window 2.1Rectangle {color: "#545454&qu ...

  3. Qt官方示例-QLineEdit编辑器

    基于QLineEdit而写的文本单行编辑器.   上手使用了该编辑器示例,并归纳出以下主要功能分享给大家. 回显模式   根据不同的场合显示字符的不同显示模式,比较常用的模式有密码模式. 使用接口: ...

  4. Qt官方示例-正则测试工具

    该正则测试工具(regularexpression)是基于Qt 5.0新引入的QRegularExpression类实现的.   QRegularExpression实现与Perl兼容的正则表达式,支 ...

  5. Qt官方示例-虚拟键盘使用

    这是一个使用Qt虚拟键盘的QML文本输入示例.   该示例提供两种使用方式:一种用于桌面平台,另一种用于嵌入式平台,本例采用嵌入式平台方式显示.它们区别是前者脱离窗口应用于全局,后者依附于窗口. di ...

  6. Qt官方示例:UI Components: Scroll Bar Example(自定义滚动条)

    此示例演示了一个自定义滚动条的方法. 自定义滚动条: import QtQuick 2.0Item {id: scrollBarproperty real position//范围是 0.0 - 1. ...

  7. Qt官方示例-计算器

    该示例显示了如何使用信号和槽来实现计算器小部件的功能,以及如何使用QGridLayout将子小部件放置在网格中. 通过绑定不同的按钮和不同的槽函数实现计算功能. private slots:void ...

  8. Qt官方示例-速度仪表盘

    该刻度盘控件为一个速度仪表盘. 预览 运行演示 分析 采用Qml语言实现: 使用到了图片素材(刻度盘,指示器,指示器阴影,覆盖层): 它结合了Image元素,Rotation变换和SpringAnim ...

  9. Qt官方示例-数字时钟

    基于QLCDNumber实现的LCD的时钟显示.   DigitalClock继承于QLCDNumber,并实现一个槽函数showTime()用来定时更新时钟显示: class DigitalCloc ...

最新文章

  1. 洛谷 P1851 好朋友
  2. ASP.NET CORE WEBAPI文件下载
  3. [转载] Python-Strings
  4. 用matalb、python画聚类结果图
  5. gvim安装及其配置
  6. python 查看excel 多少行_13行代码实现对Excel自动分表(python)
  7. 面对亚马逊和谷歌的争夺战,小企业该如何生存?
  8. stanford sentiment treebank 数据集
  9. C++杂记之this指针
  10. 分享一个好的数据集资源目录
  11. vue学习笔记-6-样式绑定
  12. MySQL 入门(六)—— 索引
  13. THREEJS基础入门
  14. Proteus 里面library文件夹找不到,怎么找到library文件夹。
  15. VS2017安装打包插件
  16. 读取二代身份证号,做个记录
  17. vlookup函数和vlookup函数与数据有效性
  18. 陀螺产业区块链第十五季 | 博雅正链RegChain
  19. 零基础入门金融风控之贷款违约预测挑战赛-task01
  20. 数据库系统概论(王珊,萨师煊版)范式之前要点一览(简略)

热门文章

  1. 重新定义汽车人机界面开发,Unity HMI模板正式开放使用
  2. 极海推出APM32A系列车规级MCU
  3. 学 Win32 汇编[24] - 移位: SHL、SHR、SAL、SAR、ROL、ROR、RCL、RCR、SHLD、SHRD
  4. 安装neurokit 的艰难历程
  5. 轻松学,Java 中的代理模式及动态代理
  6. android高德地图用地址获取经纬度,高德地图API-获取位置信息的经纬度
  7. 小米从北京迁往武汉南京,一线大厂逃离或为新常态?
  8. android 行车记录仪分析,基于Android的智能行车记录仪的设计与实现.doc
  9. u盘安装linux戴尔boot设置,戴尔台式机bios设置,详细教您如何安装U盘启动
  10. 2016年关总结 让爱更有力量