Embedding external applications into QtWidgets - reparenting QWidgets/QWindows
-
wrote on 17 May 2017, 16:17 last edited by
Hello everyone!
I am new in this blog, so first of all:
qDebug() << "Hello world! :-)";
To the real problem:
I am having trouble embedding an "external" window into my "parent" application. Both applications are Qt5-Widgets applications and created in QtCreator. The scenario is the following:A) Host application: it has a simple descriptive QLabel and a blank, empty stackedWidget below the QLabel.
B) Guest application: it has just a colored widget and a QLabel which says "Guest app"
What I want to achieve: Launch B (Guest app) from A (Host app) via a QProcess and embed B in the main stackedWidget of A, i.e., in the Host app:
QProcess p; p.setProgram("<path-to-Guest-app>"); p.setArgs("<argument-list>"); //eventually not needed since, as said, it is just a dummy app that does nothing p.start(); qDebug() << "Sucess! Child process running with pid: " << p.processId();
and then do the reparenting of the B application window into A's main stackedWidget.
So far I've tried the following:
auto *window = QWindow::fromWinId((WId)Guest_App_Window_Id); Q_ASSERT(window); qDebug() << "Assertion passed! Window may be valid"; QWidget *widget = QWidget::createWindowContainer(window); ui->stackedWidget->addWidget(widget);
But when I run it, I get the following ugly errors:
Sucess! Child process running with pid: 5981 Window id: 73400325 was obtained Assertion passed! Window may be valid QXcbConnection: XCB error: 3 (BadWindow), sequence: 361, resource id: 73400325, major code: 7 (ReparentWindow), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 362, resource id: 73400325, major code: 7 (ReparentWindow), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 363, resource id: 73400325, major code: 18 (ChangeProperty), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 364, resource id: 73400325, major code: 12 (ConfigureWindow), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 365, resource id: 73400325, major code: 7 (ReparentWindow), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 366, resource id: 73400325, major code: 18 (ChangeProperty), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 367, resource id: 73400325, major code: 8 (MapWindow), minor code: 0
Any suggestions on either how to solve this problem or how to embed/reparent an external application into another Qt widget? Any help is much appreciated :)
Best regards,
eiger824 -
Hello everyone!
I am new in this blog, so first of all:
qDebug() << "Hello world! :-)";
To the real problem:
I am having trouble embedding an "external" window into my "parent" application. Both applications are Qt5-Widgets applications and created in QtCreator. The scenario is the following:A) Host application: it has a simple descriptive QLabel and a blank, empty stackedWidget below the QLabel.
B) Guest application: it has just a colored widget and a QLabel which says "Guest app"
What I want to achieve: Launch B (Guest app) from A (Host app) via a QProcess and embed B in the main stackedWidget of A, i.e., in the Host app:
QProcess p; p.setProgram("<path-to-Guest-app>"); p.setArgs("<argument-list>"); //eventually not needed since, as said, it is just a dummy app that does nothing p.start(); qDebug() << "Sucess! Child process running with pid: " << p.processId();
and then do the reparenting of the B application window into A's main stackedWidget.
So far I've tried the following:
auto *window = QWindow::fromWinId((WId)Guest_App_Window_Id); Q_ASSERT(window); qDebug() << "Assertion passed! Window may be valid"; QWidget *widget = QWidget::createWindowContainer(window); ui->stackedWidget->addWidget(widget);
But when I run it, I get the following ugly errors:
Sucess! Child process running with pid: 5981 Window id: 73400325 was obtained Assertion passed! Window may be valid QXcbConnection: XCB error: 3 (BadWindow), sequence: 361, resource id: 73400325, major code: 7 (ReparentWindow), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 362, resource id: 73400325, major code: 7 (ReparentWindow), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 363, resource id: 73400325, major code: 18 (ChangeProperty), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 364, resource id: 73400325, major code: 12 (ConfigureWindow), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 365, resource id: 73400325, major code: 7 (ReparentWindow), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 366, resource id: 73400325, major code: 18 (ChangeProperty), minor code: 0 QXcbConnection: XCB error: 3 (BadWindow), sequence: 367, resource id: 73400325, major code: 8 (MapWindow), minor code: 0
Any suggestions on either how to solve this problem or how to embed/reparent an external application into another Qt widget? Any help is much appreciated :)
Best regards,
eiger824wrote on 18 May 2017, 03:26 last edited by@eiger824 Are you sure your window id is correct? Oh and you are running as a normal user not root right?
-
wrote on 21 May 2017, 14:30 last edited by
Hey @ambershark, thank you for your reply!
I doubt that I am getting the right window ID. In fact, when I retrieve the WId from the function call
WId id = QWidget::winId();
the result differs to the one I get when I query the window Id of the "guest" app according to http://stackoverflow.com/questions/2250757/is-there-a-linux-command-to-determine-the-window-ids-associated-with-a-given-pro
So my question(s) here remain:
1.) How can I get the window Id of the child process?
2.) How can I correctly embed my child process into my "host" application's window?Thanks again,
/eiger824 -
wrote on 22 May 2017, 11:37 last edited by
I may have found a solution in
http://stackoverflow.com/questions/33699258/qt-5-5-embed-external-application-into-qwidget
By making use of QProcess we can write the main widget's window ID to standard output from the child process and read it back from the parent process, and then create our widget according to:auto *window= QWindow::fromWinId(id); // id is the window ID of the child process Q_ASSERT(window); auto *widget = QWidget::createWindowContainer(window); //let vLayout be a QVBoxLayout object, already defined, then: vLayout->addWidget(widget); this->setLayout(vLayout);
I got it to work on Desktop Linux but when I cross compile I get the error that the window ID is bad. I guess some mismatch with the unsigned long long implementation on my processor which differ from the host processor. I'll keep investigating.
/eiger824
-
I may have found a solution in
http://stackoverflow.com/questions/33699258/qt-5-5-embed-external-application-into-qwidget
By making use of QProcess we can write the main widget's window ID to standard output from the child process and read it back from the parent process, and then create our widget according to:auto *window= QWindow::fromWinId(id); // id is the window ID of the child process Q_ASSERT(window); auto *widget = QWidget::createWindowContainer(window); //let vLayout be a QVBoxLayout object, already defined, then: vLayout->addWidget(widget); this->setLayout(vLayout);
I got it to work on Desktop Linux but when I cross compile I get the error that the window ID is bad. I guess some mismatch with the unsigned long long implementation on my processor which differ from the host processor. I'll keep investigating.
/eiger824
wrote on 22 May 2017, 21:49 last edited by@eiger824 Sorry been out camping.. no internet. ;)
Anyway, I'm glad you figured out your problem.
As for the cross compile.. What device/os are you cross compiling for? What is the bit depth? It sounds like your guess on your cast is correct. Probably assuming 64-bit but x-compiling to 32-bit?
-
wrote on 2 Jul 2018, 19:09 last edited by
@eiger824 I actually put the process thread in the same widget/window class call. I obtain the PID directly and pass it into the QWindow::fromWinId(id); but am getting this Xcb connection error, how did you read the Pid into the method please? Btw I am embedding a .jar Gui in the widget.
Thanks!