Qt实现半透明、无边框、可自由移动、不规则的窗体

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37385181/article/details/82894077

 

目录

 

预期效果

功能要点

实现步骤

进一步扩展应用


预期效果

先出示效果图一张,如果不是读者需要的,读者可以看完效果图之后就关闭本网页啦。

 

功能要点

  • 窗口无边框
  • 可自由拖动
  • 背景透明度自定义
  • 边框可设置为异形

实现步骤

                第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代码传送门:

demo代码
 

更新:2018-10-08 19:44

设置了“Tool”的flag之后,它的pos()指的是相对于整个屏幕左上角的坐标,而不是相对于父容器的坐标。如果想要知道其相对于父容器的坐标,还得知道父容器相对于整个屏幕的坐标。

展开阅读全文

没有更多推荐了,返回首页