You are not logged in.

1

Wednesday, November 30th 2011, 9:43am

Locking a QWidget ontop of another

I'm trying to put a transparent QWebView ontop of a playing VLC video.
(The aim is to use html/javascript as a GUI to control and draw ontop of the video)

If I put QWebView in the same window (same parent) as the QWidget holding libvlc, the transparency stops working over the video.
This also happens if I put QWebView in a QDialog ontop of the video.
(This problem seems onsolvable, reading other forums)

But if I but QWebView and the video in separate QWidgets, the transparency works.

So, I'd like to "lock" the QWebView ontop of a QWidget so that they act as being one. Ugly solution yes, but probably the only way.

Do you have any suggestions on how to make this possible?
To enable focus, resizing, window-tabbing, etc.

regards
Anders

Junior

Professional

  • "Junior" is male

Posts: 1,623

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

2

Wednesday, November 30th 2011, 2:40pm

You might consider a third widget (container) without any layout and overload virtual protected resizeEvent and set the geometries based on the rect of the container widget.
(example I used to simulate this was with a mainwindow without layout control)

mainwindow.h

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "ui_mainwindow.h"

class MainWindow : public QMainWindow, private Ui_MainWindow
{
    Q_OBJECT
    public:
        MainWindow( QWidget *parent = 0, Qt::WindowFlags f = 0 );
        ~MainWindow();

    protected:
         void resizeEvent( QResizeEvent *event );
};

#endif // MAINWINDOW_H


mainwindow.cpp

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "mainwindow.h"

MainWindow::MainWindow( QWidget *parent, Qt::WindowFlags f ) :
    QMainWindow( parent, f )
{
    setupUi( this );
}

MainWindow::~MainWindow()
{
}

void MainWindow::resizeEvent( QResizeEvent *event )
{
    Q_UNUSED( event );
    graphicsView->setGeometry( rect() );
    tabWidget->setGeometry( rect() );
}

3

Wednesday, November 30th 2011, 5:05pm

I think this will be a bit difficult to get working well - the user may alt-tab at anytime and bring the video on top of the transparent widget. You may be able to solve this by always passing the focus back onto the transparent/web widget.

As well as resize event, move event would also have to be considered.

I'm not sure if using a container widget would be easier or not compared to managing the widgets from the transparent widget.
If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

4

Friday, December 2nd 2011, 1:57pm

I'm pretty close to succeding now, with tracking a bunch of events (focusInEvent, moveEvent, resizeEvent, etc), and calling .raise_() each time.
Though there still are some event that aren't fireing.

I have found one event QEvent.ZOrderChange that fires correctly everytime.
This would be perfect if I could somehow find out which QWidget is on top. (If I call raise_() on every ZOrderChange i get a recursion problem)

Is there any such z-order information?
I've tried app.activeMindow(), app.topLevelWidgets(), topLevelAt() but they give the same info each time. Very strange.

Moohasha

Trainee

  • "Moohasha" is male

Posts: 55

Location: Dallas, TX

Occupation: Software Engineer

  • Send private message

5

Friday, December 2nd 2011, 2:14pm

Just set the window flags of the floating widget so that it's always on top.

Source code

1
widget->setWindowFlags(widget->windowFlags() | Qt::WindowStaysOnTopHint);


You'll still have to move it when the background widget moves or resizes and shifting focus back to the background widget, but you don't have to worry about raising it or alt-tabbing.
"The whole trouble comes from the fact that there is so much tinkering with software. It is not made in a clean fabrication process, which it should be. What we need, is software engineering." — F.L. Bauer, 1968

6

Friday, December 2nd 2011, 2:37pm

Well, but I just want it to stay on top of my application windows, not all running windows in the OS (which WindowStaysOnTopHint does).

That's why I need to fake it.

7

Friday, December 2nd 2011, 6:23pm

nekluh, you may be able to get around the recursion problem using signal/slots, and dynamically disconnecting/reconnecting them.


e.g. instead of calling raise_() directly, use a signal, and connect to some slot that does the raising. Once inside the slot:

- disconnect the widget from the signal
- do the raise - this will fire another signal, but you are no longer connected
- re-connect to the signal.

This will only work if the signal/slot are in the same thread because then the calls will be synchronous. If they are in different threads, you have a race condition.
If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

8

Sunday, December 4th 2011, 4:06pm

Damn, I really thought that would do the trick.
Though I found out that I hadn't been correct before, saying that QEvent.ZOrderChange fires every time.


There seems to be one event, which is when clicking the window titlebar, that is super crazy.
It fires QEvent.NonClientAreaMouseButtonPress and puts that QWidget in front.
But only if I click very fast, a slow click doesn't put it in front.
And when clicking fast, calling raise_() on the other QWidget doesn't help.
It overrides it, or switches windows at some later mouserelease event or something. QEvent.NonClientAreaMouseButtonRelease is NOT fired.


(QEvent.NonClientAreaMouseButtonRelease actually fires sometimes, but it doesn't help to call raise_() at that time either)


- Are there any events that I'm missing? I've overridden event() to print "all" events, but that doesn't seem to be all.
- Or can it be some kind of thread/event-order problem? (Is it possible that the windows switching happens after, not "during", the QEvent.NonClientAreaMouseButtonPress event?)