I need to set a QFrame
with a background image: http://imgur.com/RnSghvV. This is what I tried:
setAutoFillBackground(true);
setWindowFlags(Qt::FramelessWindowHint);
setStyleSheet("background: transparent;");
QPalette p = this->palette();
p.setBrush(QPalette::Base, QPixmap("ipad.png"));
this->setPalette(p);
This is what I am getting:
As you can see, there is an annoying black frame along the edges, which I want to remove, and view just the image. How do I do that?
P.S, it is possible to make it work by using the property Qt:: WA_TranslucentBackground
, as seen here. However, in my case, the QFrame will contain other subwidgets, some of them being QImages rendered through OpenGL, and setting Qt:: WA_TranslucentBackground
renders those images invisible on Windows. So I am looking for a solution which does not use this property.
Edit:
Based on a solution proposed by Evgeny, I tried this (I used 325 by 400 as dimensions for the widget because those are the dimensions of the image):
#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();
}
With this, it appears like this:
The right side and bottom are still showing grey background. If I add setStyleSheet("background: transparent")
, the grey background becomes black.
Ok, I finally got a completely working example with use of setMask
. The main problem is that your image has extra space at the border. This is the problem for OSX. At windows it works fine with original image, but for mac I had cut it.
You can get it here:
Then I could get working example on mac with QFrame
.
At .h
file:
#include <QFrame>
#include <QPixmap>
class TestFrame : public QFrame
{
Q_OBJECT
public:
TestFrame(QWidget* p = 0);
protected:
void resizeEvent(QResizeEvent* e) override;
private:
QPixmap _pix;
};
At .cpp
file:
#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());
}
Here is screenshot on OS X
The second solution is use QLabel
instead of QFrame
like this:
#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();
}
The foreground image on main window (in our case with transparency bits) can be applied like that:
#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);
}
And QLabel is derived from QFrame, so it can be applied in that same placeholder. Mind that having the main program window you need also to apply setAttribute(Qt::WA_TranslucentBackground, true)
,