把嘎嘎 2024-04-03 18:33 采纳率: 43.9%
浏览 33
已结题

qt界面实现区域透明

qt qwidget或qframe界面如何实现某个区域透明,例如三层widget,最上层的widget某个区域可以透过第二层和第三层直接看到桌面

  • 写回答

4条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2024-04-03 20:05
    关注

    【相关推荐】



    • 你可以看下这个问题的回答https://ask.csdn.net/questions/7503607
    • 你也可以参考下这篇文章:QT widget提升为自己定义的widget,Qwidget封装并嵌套使用
    • 同时,你还可以查看手册:qt QWidget 中的内容
    • 您还可以看一下 明仕强老师的Qt高级开发视频教程课程中的 QWidget类详细介绍小节, 巩固相关知识点
    • 除此之外, 这篇博客: Qt在透明QWidget上自由绘画中的 如何让QWidget变透明 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:

      先说一下被误导的尝试,关于让窗体透明,网友办法很多。

      1. setWindowOpacity(0) ;:设置完之后,窗体不会有任何显示,就像你从来没运行过程序一样。除了特殊用途,一般也不会有这种需求。
      2. setPalette(palette): 其中palette给一个透明的图片当背景,或者透明的颜色值。错误,设置完后,窗体会变成黑色。
      3. …不一一列举了…

      进入整体,其实透明窗体实现相对简单,对你想要透明的QWidget对象设置三个属性就行了(构造函数还是main函数中设置,看你心情)。伪代码如下:

      setWindowFlags(Qt::FramelessWindowHint);
      setAttribute(Qt::WA_NoSystemBackground);
      setAttribute(Qt::WA_TranslucentBackground);
      setAttribute(Qt::WA_TransparentForMouseEvents);
      

      稍微解释一下:

      • Qt::FramelessWindowHint:

        Produces a borderless window. The user cannot move or resize a borderless window via the window system.

        产生一个无边框的窗体。用户无法通过窗体系统移动窗体或者改变窗体的大小

        上面是Qt帮助文档中关于FramelessWindowHint标签的解释,该说的都说明了。需要关注的是,用户无法通过普通的方式改变窗体的大小和位置了。

      • Qt::WA_NoSystemBackground

        Indicates that the widget has no background.

        表明指定的widget没有背景。

        而默认的QWidget通常会自带一个白色的背景。计算机中,对于颜色,没有的意思一般都是黑色。例如,RGB值为0,0,0时。eum~有点懵,为啥要设置这个??不纠结

      • Qt::WA_TranslucentBackground:

        Indicates that the widget should have a translucent background, i.e., any non-opaque regions of the widgets will be translucent because the widget will have an alpha channel. Setting this flag causes WA_NoSystemBackground to be set.

        表明widget应该具有半透明的背景,即任何不透明的区域都将是半透明的。设置这个标签将导致Qt::WA_NoSystemBackground被同时设置。

        嗯~~不透明的区域半透明!!!什么鬼话。翻译一下,大概就是,应该透明的地方透明,不应该透明的地方不透明,例如:没有任何控件的地方就是应该透明的,有子QWidget或者QPainter画出的线条的地方就不是透明的。

        还有一点挺有意思的,这个标签被设置后,Qt::WA_NoSystemBackground也会被设置,所以其实伪代码中的setAttribute(Qt::WA_NoSystemBackground);是可以省略的。

      • Qt::WA_TransparentForMouseEvents:

        When enabled, this attribute disables the delivery of mouse events to the widget and its children.

        启用该属性时,将禁止想widget和它的子widget传递鼠标事件。

        这个属性后面会用,顺便在这里解释先。

      最后,来看一下每个属性的效果,我的工程主窗体就是一个普通的QWidget,方便起见,显示了一个Label,并重写了paintEvent函数,使用QPainter画了一个椭圆。源码会在文末附上。
      在这里插入图片描述

      上面是什么属性都没有设置的QWidget,蓝色文字部分是一个Label,红色的椭圆是用QPainter画在QWidget上的。我们要达到的透明效果是,只能看到蓝色文字和红色椭圆,其它都是桌面背景。下面通过属性的一步步设置,仔细观察一下界面的变化吧。
      在这里插入图片描述

      上面是setWindowFlags(Qt::FramelessWindowHint);代码执行后的界面。QWidget的标题框消失了,但是还有默认背景。
      在这里插入图片描述
      上面是setAttribute(Qt::WA_NoSystemBackground);执行后的界面,还真的变黑了。不纠结
      在这里插入图片描述

      当当当~,这不就是我要的效果么。这是执行了setAttribute(Qt::WA_TranslucentBackground);的效果。背景其实就是我的桌面背景。

      接下来一个问题就是,当QWidget变成透明背景后,居然没法响应鼠标了,鼠标的事件没有发给我的widget。来看看效果:
      在这里插入图片描述

      途中的Lable的拖动效果,是因为我重写了QWidgetmouseMoveEventmousePressEvent函数。代码大概是这样的:

      void Widget::mousePressEvent(QMouseEvent *event) {
             mousePosition = event->globalPos();
      }
      void Widget::mouseMoveEvent(QMouseEvent *event) {
             const QPoint position = pos() + event->globalPos() - mousePosition;
             move(position.x(), position.y());
             mousePosition = event->globalPos();
      }
      

      只有鼠标在Label上时,widget才能够响应鼠标的拖拽动作,在QPainter画出的红色椭圆上,鼠标的效果和在桌面的效果没啥区别。无法效应鼠标,肯定就不能作画,毕竟我们的手绘是需要靠鼠标或者触控笔输入的。那么,怎么让透明的窗体相应鼠标的各种事件呢?


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月25日
  • 创建了问题 4月3日