半透明 QWidget 应该是可点击的跨操作系统

Posted

技术标签:

【中文标题】半透明 QWidget 应该是可点击的跨操作系统【英文标题】:Translucent QWidget should be clickable cross-os 【发布时间】:2011-08-04 17:31:59 【问题描述】:

我正在尝试使用跨操作系统的 Qt (C++) 应用程序完成以下任务。 运行程序后会弹出一个新窗口,即全屏 QWidget。现在我希望它是透明/透明的,所以用户实际上不会看到它。在这个“层”上,用户可以拖动他/她的鼠标来绘制一个(红色)矩形来选择一个区域——当鼠标被释放时——截屏。

问题: 问题在于整个透明层,因为这似乎在跨操作系统时效果不佳。因为当我点击图层所在的位置时,为了调用 mousePressEvent(),我点击它到它下面的窗口,就好像它甚至不存在一样。然而,在 Ubuntu 上,我没有。我希望在 Windows 上获得相同的效果,但到目前为止我什么也没得到... (使另一个 GUI 对象出现,例如按钮,只会使按钮成为图层的可点击部分)

在 Ubuntu 11.04 32 位和 Windows 7 Home Premium 64 位上测试。 (尝试使用Mac,是否可以解决此问题。)

那么有谁知道这将如何工作? 到目前为止,我已经包含了我的代码。(清除了我所有的其他 100 次尝试。)

ma​​in.cpp 这里我设置了translucentBackground,这里我可能错过了一个设置或者配置不正确。

#include <QtGui/QApplication>
#include "widget.h"
int main(int argc, char *argv[])

    QApplication a(argc, argv);
    Widget w;
    //Fullscreen app
    w.showFullScreen();
    w.setAttribute(Qt::WA_NoSystemBackground);
    w.setAttribute(Qt::WA_TranslucentBackground);
    w.setMouseTracking(true);
    w.setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
    //Show
    w.show();
    return a.exec();

widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include "QDebug"
    Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
    
        this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
        QPalette palette(Widget::palette());
        palette.setColor(backgroundRole(), Qt::white);
        setPalette(palette);
        this->clicked = false;
        ui->setupUi(this);
    
    Widget::~Widget()
    
        delete ui;
    
    void Widget::mousePressEvent ( QMouseEvent * event )
    
        //Record start
        if (event->button() == Qt::LeftButton)
                x = event->globalX();
                y = event->globalY();
                this->clicked = true;
                width = 0;
                height = 0;
        
    
    void Widget::mouseMoveEvent ( QMouseEvent * event )
    
        if (this->clicked == true)
            int x2 = event->globalX();
            int y2 = event->globalY();
            if(x < x2)
                    width = x2 - x;
            else
                    width = x - x2;
                    //Resetting startpoint when dragging to the left side on your screen, copy from java so this doesn't actually works yet.
                    x = x - width-2;
            
            if(y < y2)
                    height = y2 - y;
            else
                    height = y - y2;
                    //Resetting startpoint when dragging to the left side on your screen, copy from java so this doesn't actually works yet.
                    y = y - height-2;
            
            //Redraw rectangle
            update();
            qDebug("wa");
        
    
    void Widget::mouseReleaseEvent ( QMouseEvent * event )
    
        if (event->button() == Qt::LeftButton)
        
            //Record end
            qDebug("-------");
            this->clicked = false;
        
    
    void Widget::paintEvent(QPaintEvent *)
    
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setPen(Qt::red);
        painter.drawRect(x,y,width,height);
    

widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtGui>
#include<QMouseEvent>
namespace Ui 
    class Widget;

class Widget : public QWidget

    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private:
    Ui::Widget *ui;
    bool clicked;
    int x,y,width,height;
    void mousePressEvent ( QMouseEvent * event );
    void mouseMoveEvent ( QMouseEvent * event );
    void mouseReleaseEvent ( QMouseEvent * event );
protected:
    void paintEvent(QPaintEvent *);
;
#endif // WIDGET_H

另外,我想我已经浏览了 Google 会在这个主题上找到的所有结果,就像 Qt 的 API 文档一样。我已经严重用完了这个选项。 (我在 Java 中开始了这个项目,但到目前为止,使用 Qt 的 C++ 似乎工作量要少得多。)

任何帮助将不胜感激!

【问题讨论】:

如果您使用自定义样式,请注意以下 qt 错误:bugreports.qt-project.org/browse/QTBUG-17548 【参考方案1】:

这是一个完整的破解方法,但这是我所知道的唯一方法。截取屏幕截图,然后将其用作小部件的背景,确保屏幕的正确部分显示在窗口中,尤其是在调整大小或移动等时。至少它是跨平台的。

然而,这也是 KDE 3 的假透明度在 ARGB 视觉效果和 X11 中不存在的东西之前实现的方式。

【讨论】:

我之前在 Java 中尝试过将屏幕截图作为透明度的东西,但这并不能提供我想要实现的流畅用户体验。因为,在截取屏幕截图和用户选择一个区域之间,屏幕上可能会发生很多事情。如果您尝试截取动画内容(例如托盘栏图标)的屏幕截图,您会错过这一点,因为您已经在查看静态屏幕。我的问题仍然是这只发生在 Windows 中,它在 Ubuntu Untiy 和 GNOME 中运行良好。

以上是关于半透明 QWidget 应该是可点击的跨操作系统的主要内容,如果未能解决你的问题,请参考以下文章

如何在半透明的 QWidget 上播放视频?

使 QT Widgets 半透明

忽略 QWidget 点击事件并将其传播到操作系统

C# Windows 窗体半透明

为 QWidget 清除透明背景

iOS在半透明view上面添加label导致label半透明