前一篇讲过不规则提示框,但是提示框的方向是固定的,不能达到随意变换方向的效果,本接讲述可以动态变换方向的提示框
先看效果图
如上图1所示,上一篇文章的代码可以达到类似效果
本片文章我只介绍变动部分,尽可能的做到详细吧
我先说原理,整个窗口包含两个布局器,水平布局和垂直布局,还有2个空间填充器,最后一个当然是显示消息的窗口,显示消息的窗口可以定制
整个窗口可以使用ui来做,也可以使用纯代码来控制,我使用了ui做布局部分,如图5,空间填充器是动态加入到布局中的,代码如下
1 case TOPLEFT://箭头朝左上 2 3 { 4 5 ui->horizontalLayout->addSpacerItem(new QSpacerItem(size().width() / 8, 0 6 7 , QSizePolicy::Maximum, QSizePolicy::Minimum)); 8 9 ui->horizontalLayout->addWidget(_p->messageWidget);//消息显示窗口 10 11 ui->horizontalLayout->setStretch(0, 1);//设置空格和窗口长度比例 12 13 ui->horizontalLayout->setStretch(1, 7); 14 15 ui->verticalLayout->insertSpacerItem(0, new QSpacerItem(0, size().height() / 2 16 17 , QSizePolicy::Minimum, QSizePolicy::Maximum)); 18 19 ui->verticalLayout->setStretch(0, 1); 20 21 ui->verticalLayout->setStretch(1, 1); 22 23 } 24 25 break; 26 27 case BOTTOMLEFT://箭头朝左下 28 29 { 30 31 ui->horizontalLayout->addSpacerItem(new QSpacerItem(size().width() / 8, 0 32 33 , QSizePolicy::Maximum, QSizePolicy::Minimum)); 34 35 ui->horizontalLayout->addWidget(_p->messageWidget); 36 37 ui->horizontalLayout->setStretch(0, 1); 38 39 ui->horizontalLayout->setStretch(1, 7); 40 41 ui->verticalLayout->addSpacerItem(new QSpacerItem(0, size().height() / 2 42 43 , QSizePolicy::Minimum, QSizePolicy::Maximum)); 44 45 ui->verticalLayout->setStretch(0, 1); 46 47 ui->verticalLayout->setStretch(1, 1); 48 49 } 50 51 break; 52 53 case BOTTOMRIGHT://箭头朝 右下 54 55 { 56 57 ui->horizontalLayout->addWidget(_p->messageWidget); 58 59 ui->horizontalLayout->addSpacerItem(new QSpacerItem(0, 0 60 61 , QSizePolicy::Expanding, QSizePolicy::Minimum)); 62 63 ui->horizontalLayout->setStretch(0, 7); 64 65 ui->horizontalLayout->setStretch(1, 1); 66 67 ui->verticalLayout->addSpacerItem(new QSpacerItem(0, 0 68 69 , QSizePolicy::Minimum, QSizePolicy::Expanding)); 70 71 ui->verticalLayout->setStretch(0, 1); 72 73 ui->verticalLayout->setStretch(1, 1); 74 75 } 76 77 break; 78 79 case TOPRIGHT://箭头朝右上 80 81 { 82 83 ui->horizontalLayout->addWidget(_p->messageWidget); 84 85 ui->horizontalLayout->addSpacerItem(new QSpacerItem(0, 0 86 87 , QSizePolicy::Expanding, QSizePolicy::Minimum)); 88 89 ui->horizontalLayout->setStretch(0, 7); 90 91 ui->horizontalLayout->setStretch(1, 1); 92 93 ui->verticalLayout->insertSpacerItem(0, new QSpacerItem(0, 0 94 95 , QSizePolicy::Minimum, QSizePolicy::Expanding)); 96 97 ui->verticalLayout->setStretch(0, 1); 98 99 ui->verticalLayout->setStretch(1, 1); 100 101 } 102 103 break;
整个窗口背景色透明后需要自己绘制窗口颜色,长款北京形状创建代码如下
1 QPainterPath rectPath, triPath; 2 3 switch (posStyle) 4 5 { 6 7 case 1: 8 9 { 10 11 rectPath.addRoundRect(QRect(size.width() / 8 12 13 , size.height() / 2 14 15 , size.width() / 8 * 7 16 17 , size.height() / 2) 18 19 , 10); 20 21 triPath.moveTo(0, 0); 22 23 triPath.lineTo(size.width() / 4, size.height() / 2); 24 25 triPath.lineTo(size.width() / 8 * 3, size.height() / 2); 26 27 triPath.lineTo(0, 0); 28 29 } 30 31 break; 32 33 case 2: 34 35 { 36 37 rectPath.addRoundRect(QRect(0 38 39 , size.height() / 2 40 41 , size.width() / 8 * 7 42 43 , size.height() / 2) 44 45 , 10); 46 47 triPath.moveTo(size.width(), 0); 48 49 triPath.lineTo(size.width() / 4 * 3, size.height() / 2); 50 51 triPath.lineTo(size.width() / 8 * 5, size.height() / 2); 52 53 triPath.lineTo(size.width(), 0); 54 55 } 56 57 break; 58 59 case 3: 60 61 { 62 63 rectPath.addRoundRect(QRect(0 64 65 , 0 66 67 , size.width() / 8 * 7 68 69 , size.height() / 2) 70 71 , 10); 72 73 triPath.moveTo(size.width(), size.height()); 74 75 triPath.lineTo(size.width() / 4 * 3, size.height() / 2); 76 77 triPath.lineTo(size.width() / 8 * 5, size.height() / 2); 78 79 triPath.lineTo(size.width(), size.height()); 80 81 } 82 83 break; 84 85 case 4: 86 87 { 88 89 rectPath.addRoundRect(QRect(size.width() / 8 90 91 , 0 92 93 , size.width() / 8 * 7 94 95 , size.height() / 2) 96 97 , 10); 98 99 triPath.moveTo(0, size.height()); 100 101 triPath.lineTo(size.width() / 4, size.height() / 2); 102 103 triPath.lineTo(size.width() / 8 * 3, size.height() / 2); 104 105 triPath.lineTo(0, size.height()); 106 107 } 108 109 break; 110 111 } 112 113 rectPath.addPath(triPath); //添加子闭合路径 114 115 return rectPath;
如此创建的提示窗口,在使用过程中需要用户根据箭头的指向 自己去移动窗口,paintEvent函数没有变化
================================================
前边介绍的这两种不规则图形的绘制都是直接绘制在窗口上的,接下来我再介绍一种绘制不规则图形的方式,只做大概讲述,具体实现代码我就不做过多的讲解 了,这种方式的原理就是贴图,我们把想要绘制的不规则图形先绘制到图片上,然后对图片做各种处理,比如旋转、镜像、平移等操作,然后在把图片绘制到窗口 上,这样做的好处是,这个不规则的形状可以随意变化,而不需要更改很多的代码。下面我写一下这种方式的伪代码
void 窗口重回函数()
{
根据QImage构造QPainter对象或者指针
构造如图1所示的不规则QPainterPath路径
使用绘图对象把该路径绘制到QImage上
使用绘图对象把QImage绘制到窗口上
}