关于无边框跨平台的方案的一些总结,也发现了一些比较蛋疼的问题,但是也有了一些相应的解决方案,现在总结下。

一。创建一个子窗口,然后设置子窗口属性为透明,无焦点(setAttribute(Qt::WA_TranslucentBackground), setFocus(Qt::NoFocus)),子窗口installEventFilter父窗口来响应父窗口的resize的事件等等。

这种方案有个好处就是,这个子窗口模块化,任何窗口都能试用。缺点也有,就是不是完全跨平台,在某些Linux桌面环境下(比如Ubuntu),会出现多余的框,这个也没有好的办法解决掉。所以结论就是Windows平台可以用这个方法,Linux平台不太建议使用。

 

二。重写对应窗口的paintevent函数。这个方法虽说不是比较好的,而且写起来很麻烦,但是想要达到我们想要的跨平台的无边框阴影的方案,还是只能选择这个,这个上个写的小demo

无边框窗口属性设置成这个。

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

 

重写paintevent函数,这里有两个解决方案,第一个是自己绘制,比我下边的代码;第二种就是重新绘制个图片,这样效率比较慢。但是代码比较好看

第一种:

QPainterPath path;
    path.setFillRule(Qt::WindingFill);
    path.addRect(10, 10, this->width()-20, this->height()-20);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.fillPath(path, QBrush(Qt::transparent));

    QColor color(0,0,0,50);
    int arr[10] = {150,120,80,50,40,30,20,10,5,5};
    for(int i=0; i<10; i++)
    {
        QPainterPath path;
        path.setFillRule(Qt::WindingFill);
        if(i == 5)
            path.addRect(10-i-1, 10-i-1, this->width()-(10-i)*2, this->height()-(10-i)*2);
        else
            path.addRoundedRect(10-i-1, 10-i-1, this->width()-(10-i)*2, this->height()-(10-i)*2,2,2);

        color.setAlpha(arr[i]);
        painter.setPen(color);
        painter.drawPath(path);
     }

最后别忘记,把这个窗口的layout的margin设置成10,看看我的paintevent,我addRect(10,—-)因为我只增加了10的宽度。懒得写了。

第二种:

QPainter painter(this);
    painter.save();
    painter.setRenderHint(QPainter::Antialiasing, true);
    QPixmap pixShadow;
    //这里pixshadow可以弄个成员变量,省的每次load
    pixShadow.load(":/shadow.png");

    painter.fillRect(-6,-6,width()+12,height()+12,QColor(0, 0, 0,0));
    painter.drawPixmap(-6,-6,width()+12,height()+12,m_pixShadow);
    painter.restore();

 

图片在这里

 

 

这种方案还有一个问题,就是这个主窗口的子控件有的白色的时候,设置成这个属性
setAttribute(Qt::WA_TranslucentBackground);
有的子控件有的会变成透明。但是也没有很好的解决方案。这里是个大坑。既然是自定义的窗口,就乖乖的多照顾下子控件吧。