PDA

View Full Version : Painting on top of QAxWidget hosted video



astodolski
29th August 2014, 14:57
I host an ActiveX control which displays video. It is wrapped in QAxWidget. I try painting within QAxWidget but it always appears behind:



void MainWindow::paintEvent(QPaintEvent* e)
{
QMainWindow::paintEvent(e);
QPainter p(this);
p.setPen(Qt::red);
p.drawRect(10,10,100,100);
}


I can see the left top and left bottom corners of the rect to know it’s drawn but don’t understand how to get the z-order changed. The items are laid out in QDesigner. Below is some of the derived header from the UI compiler:

ui_mainwindow.h


centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
gridLayout = new QGridLayout(centralWidget);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(11, 11, 11, 11);
gridLayout->setObjectName(QStringLiteral("gridLayout"));
HDVideo = new QAxWidget(centralWidget);
HDVideo->setControl(QStringLiteral("{cb1671db-6c24-4c48-b5f9-8276d135501e}"));
HDVideo->setObjectName(QStringLiteral("HDVideo"));

gridLayout->addWidget(HDVideo, 0, 0, 1, 1);


I’ve tried calling ui->HDVideo->lower as well as ui->HDVideo->stackUnder(this) which doesn’t work. How can you paint on a QAxWidget?

d_stranz
30th August 2014, 02:11
Do you call QMainWindow::setCentralWidget() somewhere with your centralWidget pointer?

In your paintEvent() method, you are painting on the MainWindow, not the QAxWidget. Z-order is defined for sibling widgets. The QAxWidget is a child of the MainWindow widget and so will always appear in front of it.

If you want your painting to appear as if it was on top of the QAxWidget, then you either need to derive your own widget from QAxWidget and override the paintEvent() to do your drawing there (after the QAxWidget has painted its contents), or create a transparent widget (QWidget::setWindowOpacity()) that is a sibling of the QAxWidget and set its size, position, and z-order to sit exactly on top of the QAxWidget (QWidget::raise() or QWidget::stackUnder()). Do your drawing on the transparent widget. You'll have to handle resize events on the main window to make sure the transparent window is always in sync with the video widget.

I don't know if you can derive from QAxWidget and make it work properly. QAxWidget is a wrapper around ActiveX controls. For painting, Qt provides a window in which the control can paint (or vice-versa - Qt hosts the control's window in the QAxWidget). The control's painting may not be handled by or synchronized with Qt's paintEvent().

astodolski
2nd September 2014, 20:37
Do you call QMainWindow::setCentralWidget() somewhere with your centralWidget pointer?

In your paintEvent() method, you are painting on the MainWindow, not the QAxWidget. Z-order is defined for sibling widgets. The QAxWidget is a child of the MainWindow widget and so will always appear in front of it.

If you want your painting to appear as if it was on top of the QAxWidget, then you either need to derive your own widget from QAxWidget and override the paintEvent() to do your drawing there (after the QAxWidget has painted its contents), or create a transparent widget (QWidget::setWindowOpacity()) that is a sibling of the QAxWidget and set its size, position, and z-order to sit exactly on top of the QAxWidget (QWidget::raise() or QWidget::stackUnder()). Do your drawing on the transparent widget. You'll have to handle resize events on the main window to make sure the transparent window is always in sync with the video widget.

I don't know if you can derive from QAxWidget and make it work properly. QAxWidget is a wrapper around ActiveX controls. For painting, Qt provides a window in which the control can paint (or vice-versa - Qt hosts the control's window in the QAxWidget). The control's painting may not be handled by or synchronized with Qt's paintEvent().

Though not explicitly shown, since I mentioned that the layout was done in designer, the call to setCentralWidget is made in the ui header file. The specific call is here:



HDVideo = new QAxWidget(centralWidget);
HDVideo->setControl(QStringLiteral("{cb1671db-6c24-4c48-b5f9-8276d135501e}"));
HDVideo->setObjectName(QStringLiteral("HDVideo"));
HDVideo->setProperty("geometry", QVariant(QRect(30, 30, 221, 161)));
HDVideo->setProperty("enabled", QVariant(true));
MainWindow->setCentralWidget(centralWidget);
HDVideo->raise();


Interesting that the layout places the object hosted by QAxWidget on top with the raise method. If I call lower() on the video object, it has no effect. If you would oblige me, I'm not sure what you mean by a transparent widget as a sibling of the QAxWidget. Would you mind an illustration (example snip)?