通常我们用到的对话框基本上都是规则的,在有些特殊情况下,也会使用到不规则窗口,那么该如何实现不规则窗体呢?
在MFC框架下很难实现,应该说是难的都想放弃,但是,Qt框架下提供了一个叫做setMask()函数,用来实现不规则窗体,为窗体设置遮罩。
在今天的功能介绍中,主要是围绕如何setMask()函数进行讲解的。首先,我们看一下实现出来的效果吧!
功能:点击鼠标左键拖动窗口进行移动,鼠标右键销毁当前窗口。
用到的事件:鼠标按下事件、鼠标拖动事件、绘图事件
具体的功能操作如下:
功能层创建
新建一个Qt Widgets Application工程,基类为:QWidget,工程名字随意就行。
事件处理
为了让不规则窗口能够通过鼠标进行随意拖动,此时需要重写鼠标事件以及绘图事件。
按下事件:mousePressEvent
cpp
void QtIrregularWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_ptDragPosition = event->globalPos() - this->frameGeometry().topLeft();
event->accept();
}
if (event->button() == Qt::RightButton)
{
close();
}
}
代码解析:
在鼠标按下事件中根据左键和右键不同响应分为了两个功能。
就拿简单的右键响应来说,触发了鼠标右键事件后,直接退出程序。
鼠标左键触发,此时,需要保存当前鼠标点所在的位置相对于窗体左上角的偏移值。使用成员变量m_ptDragPostion。
event->globalPos():获取的鼠标位置是鼠标偏离电脑屏幕左上角(x=0, y=0)的位置。
frameGeometry()->topLeft():获取包括了标题栏客户区的左上角的点位置
在这里,就有一个小疑点,geometry()与frameGeometry()究竟有什么区别呢?
geometry()获取的区域不包括标题栏和边框区域的,而frameGeometry()是包括标题栏和边框的,也就是窗口真正的区域
移动事件:mouseMoveEvent
cpp
void QtIrregularWidget::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
move(event->globalPos() - m_ptDragPosition);
}
}
代码解析:
当鼠标左键处于按下状态,且触发了mouseMoveEvent事件后,此时才会产生窗口移动效果。
移动的位置也就是由实时获取的电脑屏幕区域,减去鼠标按下时获取的最初位置。
绘图事件:paintEvent
因为添加的是不规则图片,所以,在paintEvent中需要将图片绘制到窗口中,这个没有难度。
cpp
void QtIrregularWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawPixmap(0, 0, QPixmap(":/QtIrregularWidget/image/kcfl_n.png"));
}
不规则处理
在文章开篇就说道,设置Qt框架中不规则窗体需要用到:QWidget::setMask()函数。
所谓的不规则就是为窗口设置遮罩,遮住所选区域以外的部分使其看起来是透明的,如果选择一个png图片,该图片的透明部分就是一个遮罩。
QWidget::setMask参数可以是一个QBitmap对象或者是QRegion对象,此时,只有QPixmap::mask()可以获取图片的遮罩信息,所以,在这里,参数传入的是一个QBitmap对象。
那么,实际的处理如下代码所示:
cpp
QString qsPicturePath = ":/QtIrregularWidget/image/kcfl_n.png";
QPixmap pix;
pix.load(qsPicturePath, 0, Qt::AvoidDither | Qt::ThresholdAlphaDither | Qt::ThresholdDither);
resize(pix.size());
setMask(QBitmap(pix.mask()));
代码解析:
使用QPixmap的方式加载需要展示不规则背景图,重点是load后面的第三个参数。
参数1:图片的路径
参数2:读取图片文件的格式,一般采取默认值0
参数3:读取图片的方式。
Qt::AvoidDither:(当打算保存为文件而转化时的默认项) -- 只有在图像超过256色并且它将被转化为8位时,抖动32位图像。
Qt::ThresholdAlphaDither:(默认)- 没有抖动。因为有可能填入的图片带有透明通道,所以该属性有必要存在。
Qt::ThresholdDither:没有抖动;最靠近的颜色将被使用。
根据当前加载的背景图的大小,设置窗口的整体区域,最后设置不规则方法。
到这里,一个简单的,可拖动的不规则窗口就已经实现了。
我是糯诺诺米团,一名C++开发程序媛~