[Solved] QSplashScreen using a PNG with transparent areas
-
That has a similar effect, but a mask does not make alpha, it makes transparent or not.
A top level widget (QSplashScreen is a widget) can be transparent. Sorry, I didn't read the complete article before. Currently I can't test it, but you could play with the following things:
- setWindowOpacity(xxx);
- setAttribute(Qt::WA_NoBackground);
- setAttribute(Qt::WA_NoSystemBackground);
- setAttribute(Qt::WA_TranslucentBackground);
-
[quote author="Gerolf" date="1294907465"]That has a similar effect, but a mask does not make alpha, it makes transparent or not.
A top level widget (QSplashScreen is a widget) can be transparent. Sorry, I didn't read the complete article before. Currently I can't test it, but you could play with the following things:
- setWindowOpacity(xxx);
- setAttribute(Qt::WA_NoBackground);
- setAttribute(Qt::WA_NoSystemBackground);
[/quote]
Thank you for the additional information but unfortunately it seem not to solve my problem:
setWindowOpacity(.75);
Makes the complete widget 75% translucent but does not affect the area using the alpha channel.setAttribute(Qt::WA_NoBackground);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
All tree attributes just make the background of the window black and the area involved depends on the use of setMask. -
Currently testing on OSX and Windows.
-
Use a QLabel instead.
-
if the form transparency is the problem, there wont be difference in using objects.
[quote author="peppe" date="1294920580"]Use a QLabel instead.
-
[quote author="peppe" date="1294920580"]Use a QLabel instead.
http://bugreports.qt.nokia.com/browse/QTBUG-12820[/quote]Thank you for the hint! I really seem to have hit bug 12820.
The following code seems to work as expected:
@
QPixmap aPixmap(":/splash.png");
QLabel* aWidget = new QLabel(0, Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
aWidget->setAttribute(Qt::WA_TranslucentBackground);
aWidget->setPixmap(aPixmap);
aWidget->show();
@I'm actually surprised to hit a bug in a rather prominent class like QSplashScreen. As there is no information on when this bug will be fixed it might make sense to vote for it.
Does someone eventually have a workaround to get this working in a QSplashScreen?
-
I got it working by subclassing QSplashScreen, setting QSplashScreen::setPixmap(QPixmap splash); and setting the mask to the subclass, setMask(QPixmap mask); .
Splash image with a text display:
!http://img.mobypicture.com/aa470873918e7804b36e6fb037e5b0b0_view.jpg(screencap)!
main:
@QPixmap splashImage(":images/splash.png");
QPixmap splashMask(":images/splashmask.png");customSplashScreen *splash = new customSplashScreen(splashImage);
splash->setMessageRect(QRect::QRect(7, 253, 415, 14), Qt::AlignCenter); // Setting the message position.QFont splashFont;
splashFont.setFamily("Arial");
splashFont.setBold(true);
splashFont.setPixelSize(9);
splashFont.setStretch(125);splash->setFont(splashFont);
splash->setMask(splashMask);
splash->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::SplashScreen);
splash->show();/* To intercept mousclick to hide splash screen. Since the
splash screen is typically displayed before the event loop
has started running, it is necessary to periodically call. */
app.processEvents();splash->showStatusMessage(QObject::tr("Initializing..."));@
customSplashScreen.h:
@#ifndef CUSTOMSPLASHSCREEN_H
#define CUSTOMSPLASHSCREEN_H#include <QSplashScreen>
#include <QPainter>class customSplashScreen
:public QSplashScreen
{public:
customSplashScreen(const QPixmap& pixmap);
~customSplashScreen();
virtual void drawContents(QPainter *painter);
void showStatusMessage(const QString &message, const QColor &color = Qt::black);
void setMessageRect(QRect rect, int alignment = Qt::AlignLeft);private:
QString message;
int alignement;
QColor color;
QRect rect;
};#endif // CUSTOMSPLASHSCREEN_H@
customSplashScreen.cpp:
@#include "customSplashScreen.h"customSplashScreen::customSplashScreen(const QPixmap& pixmap)
{
QSplashScreen::setPixmap(pixmap);
};customSplashScreen::~customSplashScreen()
{
};void customSplashScreen::drawContents(QPainter *painter)
{
QPixmap textPix = QSplashScreen::pixmap();
painter->setPen(this->color);
painter->drawText(this->rect, this->alignement, this->message);
};void customSplashScreen::showStatusMessage(const QString &message, const QColor &color)
{
this->message = message;
this->color = color;
this->showMessage(this->message, this->alignement, this->color);
};void customSplashScreen::setMessageRect(QRect rect, int alignement)
{
this->rect = rect;
this->alignement = alignement;
};@ -
[quote author="ucomesdag" date="1295004120"]I got it working by subclassing QSplashScreen, setting QSplashScreen::setPixmap(QPixmap splash); and setting the mask to the subclass, setMask(QPixmap mask); .
Splash image with a text display:
!http://img.mobypicture.com/aa470873918e7804b36e6fb037e5b0b0_view.jpg!
[/quote]Thank you very much!
Your approach look very promising.
How exactly did you setup (alpha channel) the two images you are using? -
-
Do you mind creating a wiki article in the "HowTo":http://developer.qt.nokia.com/wiki/Category:HowTo and/or "Code snippets":http://developer.qt.nokia.com/wiki/Category:snippets category? It would fit very well there!
-
[quote author="Volker" date="1295008017"]Do you mind creating a wiki article in the "HowTo":http://developer.qt.nokia.com/wiki/Category:HowTo and/or "Code snippets":http://developer.qt.nokia.com/wiki/Category:snippets category? It would fit very well there![/quote]
Will do so!
-
Wiki: "splashscreen snippet":http://developer.qt.nokia.com/wiki/Custom_splashscreen_with_text
-
-
I have an image with an Alpha channel: am I correct in the assumption that the image (splash.png) you've used has no alpha channel and the mask (splashmask.png) is the (1 bit) alpha channel?
-
If the above assumptions are correct I still seem to have problems with the semi-transparent parts of my image. In my case there is a shadow that uses a multibit alpha channel that is not shown correctly.
-
For now I'm only able to show my splash screen properly using the following code:
@QPixmap aPixmap(":/splash.png");
QLabel* aWidget = new QLabel(0, Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
aWidget->setAttribute(Qt::WA_TranslucentBackground);
aWidget->setPixmap(aPixmap);
aWidget->show();
@ -
Is there maybe a way to have QSplashScreen show the images in the same way as QLabel does when using the Qt::WA_TranslucentBackground attribute ?
-
Is there maybe a way to to use QLabel as an alternative to QSplashScreen and add something similar to showMessage to the QLabel ?
-
-
[quote author="Dieter" date="1295332434"]
- Is there maybe a way to have QSplashScreen show the images in the same way as QLabel does when using the Qt::WA_TranslucentBackground attribute ?[/quote]
What do you mean? Did you read the BR I posted a link to?
[quote]
- Is there maybe a way to to use QLabel as an alternative to QSplashScreen and add something similar to showMessage to the QLabel ?
[/quote]
Use an ordinary QWidget with a QVBoxLayout holding two QLabels?
-
[quote author="peppe" date="1295366429"]What do you mean? Did you read the BR I posted a link to?[/quote]
Absolutely! I'm just trying to find a solution to my specific problem.[quote author="peppe" date="1295366429"]Use an ordinary QWidget with a QVBoxLayout holding two QLabels?[/quote]
I had some problems with the Qt::WA_TranslucentBackground attribute in QWidget but QFrame seems to work as expected and I will very soon post a solution that worked for me. -
It took me a while but I have finally found a very simple and perfect solution for my problem with semitransparent images using an alpha channel with more then 1 bit.
It all comes down to use a QFrame with the Qt::WA_TranslucentBackground attribute and emulate the functionality of QSplashScreen.
I have tried to mimic as much as possible the functionality and apperance of the original QSplashScreen class but left out some methods to keep this example simple.
- This is the new CSplashScreen class that must be used instead of QSplashScreen:
@
class CSplashScreen : public QFrame
{
public:
CSplashScreen(const QPixmap& pixmap);void clearMessage();
void showMessage(const QString& theMessage, int theAlignment = Qt::AlignLeft, const QColor& theColor = Qt::black);private:
virtual void paintEvent(QPaintEvent* pe);QPixmap itsPixmap;
QString itsMessage;
int itsAlignment;
QColor itsColor;
};
@- The methods in CSplashScreen:
@
CSplashScreen::CSplashScreen(const QPixmap& thePixmap)
: QFrame(0, Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint)
, itsPixmap(thePixmap)
{
setAttribute(Qt::WA_TranslucentBackground);
setFixedSize(itsPixmap.size());
};void CSplashScreen::clearMessage()
{
itsMessage.clear();
repaint();
}void CSplashScreen::showMessage(const QString& theMessage, int theAlignment/* = Qt::AlignLeft*/, const QColor& theColor/* = Qt::black*/)
{
itsMessage = theMessage;
itsAlignment = theAlignment;
itsColor = theColor;
repaint();
}void CSplashScreen::paintEvent(QPaintEvent* pe)
{
QRect aTextRect(rect());
aTextRect.setRect(aTextRect.x()+5, aTextRect.y()+5, aTextRect.width()-10, aTextRect.height()-10);QPainter aPainter(this);
aPainter.drawPixmap(rect(), itsPixmap);
aPainter.setPen(itsColor);
aPainter.drawText(aTextRect, itsAlignment, itsMessage);
}
@A simple function to the CSplashSCreen:
@
void
test_SplashScreen()
{
class SleeperThread : public QThread
{
public:
static void msleep(unsigned long msecs) {QThread::msleep(msecs);}
};QPixmap aSplashImage(":/splash.png");
CSplashScreen* aSplashScreen = new CSplashScreen(aSplashImage);
aSplashScreen->show();for (int i = 1; i <= 5; i++)
{
aSplashScreen->showMessage(QString("Processing %1...").arg(i), Qt::AlignTop | Qt::AlignLeft, Qt::white);
SleeperThread::msleep(1000);
}delete aSplashScreen;
}
@ -
Before marking this topic as solved, I have now also added a complete example "CSplashScreen":http://developer.qt.nokia.com/wiki/QSplashScreen_replacement_for_semitransparent_images" to the "Code snippets":http://developer.qt.nokia.com/wiki/Category:snippets WiKi.
Thank you all for all your help!
-
[quote author="Gerolf" date="1295535937"]Hi Dieter,
just one note, I would make the QPainter instance an object on the stack.
And second: are you sure you want to call the default implementation for the paint event? you do all painting yourselve, don't you?[/quote]I agree (and have already changed the code snippets)