PDA

View Full Version : How to build a transparent ScrollArea widget?



myfifth
25th January 2011, 09:27
I'd like to build my own ScrollArea widget, which would be transparent if it overlaps other widgets or texts, based on QScrollArea.

Basically I set WA_NoSystemBackground attribute on both ScrollArea and its content widget, but the resulting appearance was not exactly expected.
1. the entire ScrollArea displayed a black background, I've no idea why it's black or it just meant that black represented blank background. What I expected was that it would display everything intact.
2. the button under ScrollArea can be viewed and can't respond to mouse click, this demonstrated the transparency effect partially worked, but the button was gone away while scrolling and never got repainted.
3. I'm afraid there is some extra paintings supposed to be handled in the case, but how?

I've built a quick demo to show my problem, hopefully someone could give me some reference. thx.

5820

high_flyer
25th January 2011, 09:30
I'd like to build my own ScrollArea widget, which would be transparent if it overlaps other widgets or texts, based on QScrollArea.
Do mean other widgets and text of the same application or from external applications?

myfifth
25th January 2011, 09:57
Do mean other widgets and text of the same application or from external applications?

in same app.

wysota
25th January 2011, 10:11
By overlapping do you mean overlapping with siblings, with cousins or with parent/children? Widgets shouldn't overlap with their cousins or siblings, they can (and do) only overlap with parent and children. I'm having a hard time understanding what you want to achieve and why but NoSystemBackground is not the way to go -- it is meant for top-level widgets only. In general if a widget is not a top-level widget, it is transparent by default so everything that goes under it should be visible.

myfifth
25th January 2011, 10:21
By overlapping do you mean overlapping with siblings, with cousins or with parent/children? Widgets shouldn't overlap with their cousins or siblings, they can (and do) only overlap with parent and children. I'm having a hard time understanding what you want to achieve and why but NoSystemBackground is not the way to go -- it is meant for top-level widgets only. In general if a widget is not a top-level widget, it is transparent by default so everything that goes under it should be visible.

Overlapping with siblings, that's my requirement. I know it's sort of weird.
If you can run my demo that would be more clear.

wysota
25th January 2011, 10:25
So maybe you shouldn't be using widgets but rather Graphics View (maybe with QML)? By the way, your demo doesn't really tell much of a story.

high_flyer
25th January 2011, 10:41
You might find this thread interesting:
http://www.qtcentre.org/threads/36155-Freehand-drawing-on-transparent-widget.

myfifth
25th January 2011, 10:42
So maybe you shouldn't be using widgets but rather Graphics View (maybe with QML)? By the way, your demo doesn't really tell much of a story.

I simply wanted to demenstrate my requirement. A ScrollArea covered on another sibling button, it would look transparent and it should properly function as well.
In summary, what I want is a scrollable widget, and it should be transparent, which means everything under it should be visible, including the content of parent, the siblings if overlapped, etc.

I haven't learned about QGraphicsView because I'm still not quite familiar with Qt class hierarchy.
I'll study it later anyway.
Thx.

wysota
25th January 2011, 17:25
The thing is widgets aren't supposed to overlap. You can put your scrollarea on top of another widget and without any special treatment it should be transparent. But if you start putting non-transparent stuff into it, it will not be transparent anymore.

#include <QtGui>

int main(int argc, char **argv){
QApplication app(argc, argv);
QLabel l;
l.resize(600,400);
l.setText("some very long text that is really extremely long so that it is long enough to be seen past the line edits");
QScrollArea *area = new QScrollArea(&l);
area->setGeometry(QRect(QPoint(0,0), QSize(600,400)));
area->setAutoFillBackground(false);
area->viewport()->setAutoFillBackground(false);
QWidget *w = new QWidget;
w->setAutoFillBackground(false);
QVBoxLayout *la = new QVBoxLayout(w);
for(int i=0;i<40;++i) {
QLabel *lab = new QLabel("xyz");
la->addWidget(lab);
}
area->setWidget(w);
l.show();
return app.exec();
}

myfifth
26th January 2011, 03:09
@wysota,

I see your idea. I know that widgets are generally not supposed to overlap with each other, Win32 doesn't support that too, so I chose Qt, however overlapping widget is primary requirement for me.
In my case,
1. for non-scrollable container widget, I worked it out with QFrame-subclassed widget.
2. for scrollable container widget, I still didn't figure it out.

I quickly went through QGraphicView, here's my doubts,
1. what I need is a common scrollable container widget, it's not quite matched to primary usage of QGraphicView, don't know if I got it right.
2. furthermore, there looked like no built-in QGraphicWidgets, like button, edit, etc, only a base QGraphicWidget, then I have to implement each one of them if required.

Alternatively, I'm thinking about implementing my own scrollable widget by starting from QFrame and QScrollBar, since default QScrollArea got limitations, would it be feasible?

myfifth
26th January 2011, 09:17
The thing is widgets aren't supposed to overlap. You can put your scrollarea on top of another widget and without any special treatment it should be transparent. But if you start putting non-transparent stuff into it, it will not be transparent anymore.

#include <QtGui>

int main(int argc, char **argv){
QApplication app(argc, argv);
QLabel l;
l.resize(600,400);
l.setText("some very long text that is really extremely long so that it is long enough to be seen past the line edits");
QScrollArea *area = new QScrollArea(&l);
area->setGeometry(QRect(QPoint(0,0), QSize(600,400)));
area->setAutoFillBackground(false);
area->viewport()->setAutoFillBackground(false);
QWidget *w = new QWidget;
w->setAutoFillBackground(false);
QVBoxLayout *la = new QVBoxLayout(w);
for(int i=0;i<40;++i) {
QLabel *lab = new QLabel("xyz");
la->addWidget(lab);
}
area->setWidget(w);
l.show();
return app.exec();
}

hi wysota, I finally figured it out.
Just moved your code
line 13 w->setAutoFillBackground(false)
below
line 19 area->setWidget(w);

I just reviewed source code of setWidget(), unfortunately it set w->setAutoFillBackground(true) by default, so we have to reset it to false after that, then it went right.

thx all.