Qt - 在不使用 WA_TranslucentBackground 的情况下以图像作为背景渲染 QFrame

Qt - render QFrame with image as background without using WA_TranslucentBackground

我需要设置 QFrame 背景图片:http://imgur.com/RnSghvV。这是我试过的:

setAutoFillBackground(true);
setWindowFlags(Qt::FramelessWindowHint);
setStyleSheet("background: transparent;");
QPalette p = this->palette();
p.setBrush(QPalette::Base, QPixmap("ipad.png"));
this->setPalette(p);

这就是我得到的:

如您所见,边缘有一个烦人的黑框,我想将其删除,然后只查看图像。我该怎么做?

P.S,可以使用 属性 Qt:: WA_TranslucentBackground 使其工作,如 所示。然而,在我的例子中,QFrame 将包含其他子部件,其中一些是通过 OpenGL 渲染的 QImages,设置 Qt:: WA_TranslucentBackground 使这些图像在 Windows 上不可见。所以我正在寻找一个不使用这个 属性.

的解决方案

编辑:

根据 Evgeny 提出的解决方案,我尝试了这个(我使用 325 x 400 作为小部件的尺寸,因为这些是图像的尺寸):

#include <QApplication>
#include <QLabel>
#include <QBitmap>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QLabel l;
    l.setWindowFlags(Qt::FramelessWindowHint);
    QPixmap p(":/img/ipad.png");
    l.setPixmap(p);
    l.setScaledContents(true);
    l.resize(300, 500); //just to test my idea
    l.setMask(p.scaled(l.width(),l.height(),Qt::IgnoreAspectRatio,
    Qt::SmoothTransformation).mask());
    l.show();
    return a.exec();
}

有了这个,它看起来像这样:

右侧和底部仍然显示灰色背景。如果我添加 setStyleSheet("background: transparent"),灰色背景变为黑色。

main window 上的前景图像(在我们的例子中有透明度位)可以像这样应用:

#include "mainwindow.h"
#include <QLabel>
#include <QPixmap>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent, Qt::FramelessWindowHint)
{
    setAttribute(Qt::WA_TranslucentBackground, true);
    setStyleSheet("background-color: rgba(255, 255, 255, 255);"); // preventing child widgets from not being drawn

    QLabel* pImageLabel = new QLabel;
    QPixmap pixmap(":/RnSghvV.png");
    pImageLabel->setPixmap(pixmap);

    setCentralWidget(pImageLabel);
}

QLabel 是从 QFrame 派生出来的,所以它可以应用在同一个占位符中。请注意,拥有主程序 window 还需要应用 setAttribute(Qt::WA_TranslucentBackground, true)

好的,我终于得到了一个使用 setMask 的完整示例。主要问题是您的图像在边框处有额外的 space 。这是 OSX 的问题。在 windows 时,它可以很好地处理原始图像,但在 mac 时,我已经将其剪掉了。 你可以在这里得到它:

然后我可以在 mac 上使用 QFrame 获得工作示例。

.h 文件:

#include <QFrame>
#include <QPixmap>

class TestFrame : public QFrame
{
    Q_OBJECT
public:
    TestFrame(QWidget* p = 0);

protected:
    void resizeEvent(QResizeEvent* e) override;

private:
    QPixmap _pix;
};

.cpp 文件:

#include <QBitmap>

TestFrame::TestFrame(QWidget *p) :
    QFrame(p, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint),
    _pix(":/img/i2.png")
{
    QPalette pal = palette();
    pal.setBrush(QPalette::Background, QBrush(_pix));
    setPalette(pal);
    resize(_pix.width(), _pix.height());
}

void TestFrame::resizeEvent(QResizeEvent *e)
{
    QFrame::resizeEvent(e);
    setMask(_pix.scaled(size()).mask());
}

这是 OS X

上的屏幕截图

第二种解决方案是使用 QLabel 而不是 QFrame,如下所示:

#include <QApplication>
#include <QLabel>
#include <QBitmap>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QLabel l;
    l.setWindowFlags(Qt::FramelessWindowHint);
    QPixmap p(":/img/ipad.png");
    l.setPixmap(p);
    l.setScaledContents(true);
    l.resize(300, 500); //just to test my idea
    l.setMask(p.scaled(l.width(),l.height(),Qt::IgnoreAspectRatio,
    Qt::SmoothTransformation).mask());
    l.show();
    return a.exec();
}