目录
预期效果
先出示效果图一张,如果不是读者需要的,读者可以看完效果图之后就关闭本网页啦。
功能要点
- 窗口无边框
- 可自由拖动
- 背景透明度自定义
- 边框可设置为异形
实现步骤
第1步:新建一个QWidget的子类,这里命名为BaseWidget
第2步:设置关键成员
private:
QRect m_areaMovable;//可移动窗口的区域,鼠标只有在该区域按下才能移动窗口
bool m_bPressed;//鼠标按下标志(不分左右键)
QPoint m_ptPress;//鼠标按下的初始位置
第3步:实现三个虚函数
(1)头文件里添加以下代码
protected:
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
(2) cpp文件添加
BaseWidget::BaseWidget(QWidget *parent) :
QWidget(parent)
{
//设置无边框透明
setWindowFlags(Qt::FramelessWindowHint|Qt::Tool);//无边框
this->setStyleSheet(QString("background-color: rgb(0, 255, 0);"));
m_bPressed = false;
}
void BaseWidget::setAreaMovable(const QRect rt)
{
if(m_areaMovable != rt)
{
m_areaMovable = rt;
}
}
void BaseWidget::mousePressEvent(QMouseEvent *e)
{
//鼠标左键
if(e->button() == Qt::LeftButton)
{
m_ptPress = e->pos();
m_bPressed = m_areaMovable.contains(m_ptPress);
setAreaMovable(this->rect());
}
}
void BaseWidget::mouseMoveEvent(QMouseEvent *e)
{
if(m_bPressed)
{
move(pos() + e->pos() - m_ptPress);
}
}
void BaseWidget::mouseReleaseEvent(QMouseEvent *e)
{
m_bPressed = false;
}
在MainWindow.cpp中使用:
bsw = new BaseWidget(this);
bsw->resize(100,100);
bsw->show();
以上代码可以实现:无边框、透明、可拖动
但是呢,鼠标只有落在左上角区域时才能拖动,于是改进一步:
void BaseWidget::showEvent(QShowEvent *)
{
setAreaMovable(this->rect());
}
这样就可以实现点击窗体的任何处进行拖动啦
进一步扩展应用
不过可能有人的需求是实现异形窗口,我的demo思路是:新建一个QLabel 子类,然后设置窗口背景透明,添加一个png图片。
异形无边框半透明窗口实现如下:
第1步:在作图软件中制作一张大小合适的png图片
第2步:读取图片并显示到控件上
在构造函数里添加:
QImage img;
img.load("arrowhead.png");
this->setPixmap(QPixmap::fromImage(img));
最终效果如下:
在分享代码之前,想先分享总结:
第1个坑:原本我是想把控件设置为悬浮的,于是新建了QDialog子类还设置了setWindowFlags(Qt::Popup),但是这样一来,这个窗口的优先级就凌驾于其他所有窗口以及所有控件之上,意味着,这个不能点击关闭的窗口还拦着我不让我与其他控件 产生交互。
后来使用了Qt::Tool这个flag,情况好转。
第2个坑:在往QLabel子类中设置图片时,使用了
QPicture temp;
temp.load("arrowhead.png");
this->setPixmap(temp);
但是出现了报错:QPicturePaintEngine::checkFormat: Incorrect header
我现在不是很懂这是为啥……【擦汗】,但是我找到了可以绕开它达成目的的方法:
QImage img;
img.load("arrowhead.png");
this->setPixmap(QPixmap::fromImage(img));
说完两个坑之后,向大家推荐一款免费的录屏软件,可以制作成gif图~网址如下
https://download.csdn.net/download/daf3707/10044739
最后,结尾了,感谢网上那些无私分享技术的人,本次学习参考了以下关键博文:
http://www.cnblogs.com/xiongxuanwen/p/5384103.html
http://ju.outofmemory.cn/entry/162211
最后,我的demo代码传送门:
更新:2018-10-08 19:44
设置了“Tool”的flag之后,它的pos()指的是相对于整个屏幕左上角的坐标,而不是相对于父容器的坐标。如果想要知道其相对于父容器的坐标,还得知道父容器相对于整个屏幕的坐标。