Results 1 to 6 of 6

Thread: Render OpenGL based widget inside a QFrame with translucent background on Windows

  1. #1
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Render OpenGL based widget inside a QFrame with translucent background on Windows

    I am making a desktop carousel app. There I need to show image widgets, which might contain other sub-widgets as well. For that I am using a QFrame with the required image as background. Here is the image I am trying to use: image. What I want is that only the image shows up, no background image or anything shows up as well, so to the user it looks like just the image. Qt provides a flag called Qt::WA_TranslucentBackground to do that. With it, this code works fine:

    Qt Code:
    1. #ifndef main_h
    2. #define main_h
    3.  
    4. #include <QFrame>
    5. #include <QPixmap>
    6.  
    7. class MyFrame : public QFrame
    8. {
    9. public:
    10. MyFrame(QWidget * parent);
    11.  
    12. virtual void paintEvent(QPaintEvent * e);
    13.  
    14. private:
    15. QPixmap _pixmap;
    16. };
    17.  
    18. #endif
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include <QApplication>
    2. #include <QPainter>
    3. #include "main.h"
    4.  
    5. MyFrame :: MyFrame(QWidget * parent) : QFrame(parent, Qt::Window|Qt::FramelessWindowHint)
    6. {
    7. setAttribute(Qt::WA_TranslucentBackground);
    8.  
    9. _pixmap.load("/Users/jaf/iPad_Vector.png");
    10. resize(_pixmap.size());
    11. }
    12.  
    13. void MyFrame :: paintEvent(QPaintEvent * /*e*/)
    14. {
    15. QPainter p(this);
    16. p.drawPixmap(0,0,width(),height(), _pixmap);
    17. }
    18.  
    19. int main(int argc, char ** argv)
    20. {
    21. QApplication app(argc, argv);
    22.  
    23. MyFrame f(NULL);
    24. f.show();
    25.  
    26. return app.exec();
    27. }
    To copy to clipboard, switch view to plain text mode 


    However, the problem is that the iPad frame needs to show other elements within it (in the viewport area), and those elements are drawn and rendered through OpenGL, and OpenGL rendered elements show up as completely blank when placed in an element with the property Qt::WA_TranslucentBackground (I don't know whether it is a Qt or OpenGL bug or expected behavior) . As a result, the viewport shows up just like it is in the original iPad image, because the new widget that is supposed to sit there on top of it shows blank.

    This happens only in Windows. Works fine in Mac. Is there any way to fix this? (Calling native C++ APIs on Windows is acceptable. C# as well, provided they can be called through Qt, like we can call native Cocoa code on Mac from Qt)

    Or can the iPad image be used as background in any other way?

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Render OpenGL based widget inside a QFrame with translucent background on Windows

    What if, instead of directly painting into the frame, you give it a child derived from QOpenGLWidget and implement your image painting as an OpenGL texture mapped onto the frame rect?

  3. The following user says thank you to d_stranz for this useful post:

    Cupidvogel (1st January 2016)

  4. #3
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Render OpenGL based widget inside a QFrame with translucent background on Windows

    That could have been a solution, but the rendering of the child widget is not in our hands, so it will take time to make that work. Meanwhile, I have another solution in mind, to draw the child widget separately as another window. But there are problems with that:

    I have two windows say A and B, A being the iPad image widget (QFrame) and B being the child widget rendered through OpenGL. I need B to always stay on top of A. The ideal way would have been to make B a child widget within A, and it was working fine, but due to the above reasons, and we have to move out B out of A and make it a standalone window. So now we have to ensure that B is a separate window and always appears on top of A. This we can do through raise() call on B and always call it when we detect a click on A to ensure that even though A has been clicked, B is still on top of it.

    Problem is, Mac has a feature called Mission Control, where you can now see both windows separately, and there if you click A, the app will show up maximized with A on top of B (and since A is bigger than B size wise, it covers up B completely and there is no way to go back without launching Mission Control again and choosing B! And we cannot detect a click on A there, plus more importantly, we don't want to show B as a separate widget). So I though about making B a tool widget, so that only A shows up in Mission Control, and clicking it does not alter the behavior of a tool widget B, which continues to remain on top.

    I first tried this:

    Qt Code:
    1. QFrame* b = new QFrame();
    2. b->setGeometry(400,40,40,100);
    3. b->setStyleSheet("background: green;");
    4. b->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
    5. b->show();
    To copy to clipboard, switch view to plain text mode 

    This works, B does not show up as a separate window in Mission Control and stays on top of A. Until you open a normal Finder window and see B disappearing. From this link, it looks like a known feature, and the suggested workaround is to set the Qt::WA_MacAlwaysShowToolWindow flag to true, which I tried next:

    Qt Code:
    1. QFrame* b = new QFrame();
    2. b->setGeometry(400,40,40,100);
    3. b->setStyleSheet("background: green;");
    4. b->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
    5. b->setAttribute(Qt::WA_MacAlwaysShowToolWindow,true);
    6. b->show();
    To copy to clipboard, switch view to plain text mode 

    Same effect, the tool widget always hides when the app loses focus. So I decided to try TooTip, and came up with this:

    Qt Code:
    1. QFrame* b = new QFrame();
    2. b->setGeometry(400,40,40,100);
    3. b->setStyleSheet("background: green;");
    4. b->setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
    5. b->show();
    To copy to clipboard, switch view to plain text mode 

    Now this works, does not hide the tool widget when app loses focus. But the problem is, it never hides at all! Even if you click other applications and they come into view, the widget B appears on top of them as well! I added this line to see if it works, it didn't. Same result:

    Qt Code:
    1. b->setAttribute(Qt::WA_MacAlwaysShowToolWindow,false);
    To copy to clipboard, switch view to plain text mode 

    So I next tried

    Qt Code:
    1. b->setWindowFlags(Qt::FramelessWindowHint | Qt:: WindowStaysOnTopHint);
    To copy to clipboard, switch view to plain text mode 

    This also behaves in the same way as ToolTip, B always stays on top of all other applications, there doesn't seem to be a way to hide it.

    If I can do this, this will be a good replacement solution in place of drawing B inside A, thus we can draw A smoothly and put B on top of it without it being affected.
    Last edited by Cupidvogel; 1st January 2016 at 22:57.

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Render OpenGL based widget inside a QFrame with translucent background on Windows

    Wish I could be of help, but I know nothing of Macs.

  6. #5
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Render OpenGL based widget inside a QFrame with translucent background on Windows

    Well, let's hope somebody who does can help..


    Added after 11 minutes:


    Is there any other possible way to render the iPad image as background of the parent QFrame without using WA_TranslucentBackground property?
    Last edited by Cupidvogel; 1st January 2016 at 23:18.

  7. #6
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Render OpenGL based widget inside a QFrame with translucent background on Windows

    Hmm. Looks like this is a known issue. Qt, at least as of 5.3.1 never implemented the WA_MacAlwaysShowToolWindow feature at all, so setting it to true will have no effect. This native Objective C code can be compiled along with my Qt code, passing in pointer to my B widget to this method (before it we have to add the Qt::Tool property):

    Qt Code:
    1. void preventHidingOnFocusOut(QWidget* aWidget)
    2. {
    3. [[reinterpret_cast<NSView *>(aWidget->winId()) window] setHidesOnDeactivate:NO];
    4. }
    To copy to clipboard, switch view to plain text mode 

    However, this brings back the same issue as using Qt::ToolTip - it stays on top of other applications as well. Source - https://bugreports.qt.io/browse/QTBUG-29816

Similar Threads

  1. translucent background - no mouse event
    By Talei in forum Qt Programming
    Replies: 4
    Last Post: 8th April 2014, 14:42
  2. Replies: 1
    Last Post: 2nd November 2011, 21:30
  3. translucent background (on Gnome)
    By drus in forum Qt Programming
    Replies: 0
    Last Post: 31st May 2010, 09:23
  4. Translucent window background in 4.3.2 - possible?
    By dpimka in forum Qt Programming
    Replies: 2
    Last Post: 15th July 2009, 09:53
  5. QFrame parent, QGLWidget-based child
    By philski in forum Qt Programming
    Replies: 6
    Last Post: 28th August 2006, 19:14

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.