PDA

View Full Version : Problems with drawing image in paintEvent of QTreeView



Tito Serenti
23rd December 2008, 23:46
Hi, I'm trying to put a background image in a QTreeView, but I can't use styles because the image needs to be loaded from a QByteArray. I've implemented this paint event, and the image gets drawn, but when I scroll the tree view, it doesn't re-draw the image. It just scrolls off the view and disappears. When I click inside the tree view or re-size, it gets re-drawn where it's supposed to be. Any ideas on how I can make the tree view redraw the image while scrolling? Thank you in advance!


void TreeView::paintEvent(QPaintEvent *event)
{
QPainter painter(viewport());
painter.drawImage(imageLeftMargin, imageTopMargin, image);
painter.end();
QTreeView::paintEvent(event);
event->accept();
};

aamer4yu
24th December 2008, 04:49
try calling update of tree view on scroll of the view

jpn
24th December 2008, 11:22
I suppose QTreeView::drawRow() or a custom delegate would be better place to draw such things.

Tito Serenti
24th December 2008, 14:12
Thank you for your suggestions. Unfortunately neither calling update (nor repaint) from any scrolling events helps. It's really odd, because it should, theoretically. Drawing the picture inside drawRow doesn't help either. It still doesn't update it when scrolling. I'll look into creating a custom delegate... I was hoping it'd be something simple, heh. I'm translating an application from Delphi, where those kinds of things are pretty straightforward. But then, I can't complain, because I like Qt infinitely better on most other fronts.

The background picture works really nicely with styles and that would be my preferred solution, but I have to save the picture into a temporary file to load it via a style (background-image: url(xxx)). Is there a way to use this method without saving the file to disk? I tried creating a custom resource, but it only works with rcc files, and I don't want to have to run an external resource compiler to create an rcc file from the picture, since I'll need to save the picture to disk to do that anyway. Any further suggestions before I spend the next week trying to figure out how to create a custom delegate? (Which might or might not work?) Thank you for your time!

jpn
24th December 2008, 14:22
Wait a minute, I think I misunderstood the problem. You want to paint a single background image for the tree view, right? Then forget about drawRow() and custom delegate. How do you calculate imageLeftMargin and imageTopMargin?

Tito Serenti
24th December 2008, 15:02
Yes, I want to draw a single background image for the entire tree. The image itself, the left and the right margins are set by the user in the tree properties dialog. So all I need to do is just draw the image at the given coordinates. And I want it to stay there in a fixed position, like it would when applying "background-attachment: fixed". I'm glad to hear you misunderstood the question, that gives me some hope that there's a simple solution :).

jpn
24th December 2008, 22:19
The problem is that item views (or delegates) fill the background with QPalette::Base. You can set the view background as transparent with good old palette:


QPalette pal = viewport()->palette();
pal.setColor(QPalette::Base, Qt::transparent);
viewport()->setPalette(pal);

or with style sheets:


viewport()->setStyleSheet("background: transparent");

Once you've done that, you can paint the image like you want before calling the base class implementation of paintEvent(). If you want to re-enable the base background you can do it for example like this:


void TreeView::paintEvent(QPaintEvent *event)
{
QPainter painter(viewport());
painter.fillRect(event->rect(), palette().base()); // <---
painter.drawImage(imageLeftMargin, imageTopMargin, image);
painter.end();
QTreeView::paintEvent(event);
}

Tito Serenti
24th December 2008, 23:25
Wonderful, it's working just like I wanted it to! Thank you for your help!