Reputation: 71
I need to recreate the Windows 7 theme where the application window header is transparent and displays blurred screen contents. My idea was to capture the screen contents and display them blurred in the header. For that reason I extended QQuickPaintedItem.
Here is the header:
class DesktopImage : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(int desktopX READ desktopX WRITE setDesktopX NOTIFY desktopXChanged)
Q_PROPERTY(int desktopY READ desktopY WRITE setDesktopY NOTIFY desktopYChanged)
public:
explicit DesktopImage(QQuickItem *parent = nullptr);
void paint(QPainter *painter) override;
int desktopX() const;
void setDesktopX(int desktopX);
int desktopY() const;
void setDesktopY(int desktopY);
signals:
void desktopXChanged();
void desktopYChanged();
private:
void grabScreensContent();
private:
QPixmap mScreensContent;
int mDesktopX;
int mDesktopY;
};
the grabScreensContent() method do as the name suggest. The paint() method is implemented as follows:
void DesktopImage::paint(QPainter *painter)
{
QRectF target(0, 0, width(), height());
QRectF source(mDesktopX, mDesktopY, width(), height());
painter->drawPixmap(target, mScreensContent, source);
}
on the QML side, I use the type as follows:
DesktopContent {
id: desktop
desktopX: window.x
desktopY: window.y
width: parent.width
height: parent.height
}
as you can see the desktopX (desktopY) properties are bound to the window x (window y) properties so that when the user moves the window the portion of the background that needs to be drawn is properly fetched. However the drawing is not as fluid as one might expect. Here is the result:
Can someone suggest an performance improvement?
Upvotes: 1
Views: 491
Reputation: 8718
Take care of renderTarget by setting it to FramebufferObject. This basically should make it as efficient as normal QML rendering yet you can use QPainter
which is sometimes conveninent.
DesktopImage::DesktopImage(QQuickItem *parent)
{
// this setting is not default
this->setRenderTarget(QQuickPaintedItem::FramebufferObject);
}
Also, only operate with the limited screen area if you don't need the whole screen. This may or may not help depending on the platform / implementation but I always limit the scope on the target first and then position the source within it. The low level painting is not necessarily very intelligent and may expect many changes across the whole area. So we should rather specify the minimum target area and just alter it (this case works like that).
void DesktopImage::paint(QPainter *painter)
{
QRectF target(mDesktopX, mDesktopY, width(), height()); // now limited
QRectF source(0, 0, width(), height()); // now within smaller target
painter->drawPixmap(target, mScreensContent, source);
}
Upvotes: 2