QWindow, QWidget, Qt5, X11Embedding how?
-
I have several applications which are developed using QX11Embed* in Qt4.8. Now i am trying to migrate to Qt5.So after some reading i found functions like
@QWindow@and
@createWindowContainer@
are used for embedding other windows and applications.
But using QWindow and createWindowContainer to create such application is very difficult and there needs to be more work done for QWindow for painting and rendering.is there any other way in Qt5.1(in Qt5.0 createWindowContainer is not available) to embed widgets and application by using simple QWidgets and other container functions.
unfortunately createWindowContainer takes only QWindow as the argument and i cannot use that function.
Regards,
Dcqt. -
All the x11 stuff has moved to the "extras" department found on Gitorious. (QX11EmbedWidgets and QX11EmbedContainer and the likes are not in 5.x)
Try this:
http://qt-project.org/doc/qt-5.1/qtx11extras/qx11info.html -
Thanks for the quick reply.
In fact i have gone through all those links but none mentioned about replacement of those functions(QX11EmbedWidgets and QX11EmbedContainer).
Any idea on how to embed widgets in Qt5.1.I have been searching for the functions for months but could not succeed.
-
I think you need to choose the source components and build those.
When you download and install QT you have an option to include source components.
This gives you among other things a QT project file named "qtx11extras.pro", that contains:@
requires(qtHaveModule(widgets))
load(qt_parts)
@then in the "src.pro" you have:
@
TEMPLATE = subdirs
contains(QT_CONFIG, xcb) {
SUBDIRS += x11extras
}
@These files defines functions that lets you query X11 for info and where to put your widgets, like:
@
int QX11Info::appScreen()
{
if (!qApp)
return 0;
QDesktopWidget *desktop = QApplication::desktop();
return desktop->primaryScreen();
}
@I'm on seriously thin ice here, not really knowing what the heck I'm talking about, but hopefully it may contain a clue....
-
Hi,
In Qt 5.1, use "QWindow::fromWinId()":http://qt-project.org/doc/qt-5.1/qtgui/qwindow.html#fromWinId followed by QWidget::createWindowContainer(). This is similar to constructing a QX11EmbedWidget and then calling QX11EmbedWidget::embedInto().
Note: The QWindow can be a standalone window. If you don't need QWidgets, you don't need to call QWidget::createWindowContainer()
[quote author="cseder" date="1381182948"]I think you need to choose the source components and build those.[/quote]It makes no sense to install the source components and then compile that source yourself. If it's in "source components", then you can already install the pre-built (and tested) binaries.
-
[quote author="JKSH" date="1381201648"]Hi,
In Qt 5.1, use "QWindow::fromWinId()":http://qt-project.org/doc/qt-5.1/qtgui/qwindow.html#fromWinId followed by QWidget::createWindowContainer(). This is similar to constructing a QX11EmbedWidget and then calling QX11EmbedWidget::embedInto().
[/quote]Hi,
Thanks for your post.
There is an example program here using QWindow and createWindowContainer.(By me some time back)http://www.qtcentre.org/threads/54922-Qt5-and-embedwidgets?p=246367&highlight=#post246367
but problem is the window is some times getting embedded and some times not.
One more thing, I have several applications which are using QWidget for which i can add layout and add a QWebView for displaying a web page of my choice, but QWindow does not allow layouts, if i want to add a QWebView to QWindow , How can that be done?
In any ways using QWindow and createWindowContainer needs a lot of work(need to send winid from client to main application) and lot of paintings and rendering.
if there is no option i will go with this option or else please suggest me alternate.
-
[quote author="cseder" date="1381182948"]I think you need to choose the source components and build those.[/quote]It makes no sense to install the source components and then compile that source yourself. If it's in "source components", then you can already install the pre-built (and tested) binaries.[/quote]
And that's why I said:
[quote author="cseder" date="1381182948"]
I’m on seriously thin ice here, not really knowing what the heck I’m talking about, but hopefully it may contain a clue….[/quote] -
in the following site it is mentioned that embedding widgets can be done using OpenGL Widgets, but there are no proper examples available .
http://qt.developpez.com/doc/4.7/qt-embeddedlinux-opengl/
can any one post some basic example about embedding widget, so that i will build on that.
Thanks.
-
[quote author="Dcqt" date="1381214297"]problem is the window is some times getting embedded and some times not.[/quote]Hmm... that sounds like a bug, either in Qt or your code.
Can you give more details on when your embedding succeeds, and when it fails?
[quote]One more thing, I have several applications which are using QWidget for which i can add layout and add a QWebView for displaying a web page of my choice, but QWindow does not allow layouts, if i want to add a QWebView to QWindow , How can that be done?[/quote]QWidget::createWindowContainer() converts a QWindow into a QWidget. After you convert, you can add it to another widget's layout.
[quote]In any ways using QWindow and createWindowContainer needs a lot of work(need to send winid from client to main application) and lot of paintings and rendering.[/quote]What do you mean? Is it more work than QX11EmbedWidget?
-
The following is what i was using in Qt 4.8 for embedding widgets.
Now i need to port this code to Qt 5 , for that i need embedx11 equivalent functions.
the link provided above is the version i was using in Qt 5 , but it is having the said problems.(i will copy the code here if you would like)
will you please go through this and suggest me based on that.
i am splitting this reply into two posts because of max number of characters limitation.applicationwindow.cpp
@#include "applicationwindow.h"
ApplicationWindow::ApplicationWindow(QWidget *parent) :
QWidget(parent)
{}
ApplicationWindow::ApplicationWindow(int min_width,int min_height,int max_width,int max_height,QWidget* parent)
:min_width(min_width),min_height(min_height),max_width(max_width),max_height(max_height),QWidget(parent)
{}
QX11EmbedContainer* ApplicationWindow::createApplicationWindow()
{
window = new QX11EmbedContainer();
window->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
QPalette pl = QPalette();
pl.setColor(QPalette::Window,Qt::black);
window->setAttribute(Qt::WA_PaintOnScreen,true);
window->setPalette(pl);
window->setMouseTracking(true);
window->setMinimumSize(min_width,min_height);
window->setMaximumSize(max_width,max_height);
return window;
}ApplicationWindow::~ApplicationWindow()
{
}
@applicationwindow.h
@#ifndef APPLICATIONWINDOW_H
#define APPLICATIONWINDOW_H#include <QWidget>
#include <QX11EmbedContainer>class ApplicationWindow : public QWidget
{
Q_OBJECT
public:
explicit ApplicationWindow(QWidget parent = 0);
explicit ApplicationWindow(int min_width,int min_height,int max_width,int max_height,QWidget parent=0);
QX11EmbedContainer* createApplicationWindow();public:
virtual ~ApplicationWindow();
private:
int max_width;
int max_height;
int min_width;
int min_height;QX11EmbedContainer* window;
signals:
public slots:
};
#endif // APPLICATIONWINDOW_H
@
main.cpp
@#include "mainwindow.h"
MainWindow *Container;
int main(int argc, char *argv[])
{
QApplication qapp(argc, argv);
Container = new MainWindow();
Container->show();
return qapp.exec();
}@
mainwindow.cpp
@#include "mainwindow.h"
#define HEIGHT 708
#define FTP_HEIGHT 60
#define WIDTH 196#define HELLOTEST "../hellotest/hellotest"
extern MainWindow *Container;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{ApplicationProcess = NULL; QWidget* mainwindow = new QWidget(); getDisplayProperties(&max_width,&max_height); setWindowMinimumSizes(max_width - 300,HEIGHT - 100); setWindowMaximumSizes(max_width,max_height); createActions(); createMenus(); mainwindow->setMinimumSize(min_width,min_height); mainwindow->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); mainwindow->setMaximumSize(max_width,max_height); setCentralWidget(mainwindow); QPalette pl ; pl.setColor(pl.Background,Qt::white); mainwindow->setAutoFillBackground(true); mainwindow->setPalette(pl); vLayout = new QVBoxLayout(); mainLayout = new QHBoxLayout(); vWidget = new QWidget(); appwindow = new ApplicationWindow (min_width - WIDTH ,min_height - (FTP_HEIGHT + 105),max_width - WIDTH,max_height - (100 +FTP_HEIGHT ) ); display = appwindow->createApplicationWindow(); vWidget->setLayout(vLayout); vLayout->addWidget(display); vLayout->setSpacing(1); mainLayout ->addWidget(vWidget); mainwindow ->setLayout(mainLayout); vLayout->setContentsMargins(0,0,0,0); display->setContentsMargins(0,0,0,0); mainwindow->setContentsMargins(0,0,0,0); mainwindow->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); display->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
}
void MainWindow::getDisplayProperties(int* width,int* height )
{
int x = 0,y = 0;
QRect rec;
QDesktopWidget D;
rec = D.geometry();
rec.getRect(&x,&y,width,height);
}void MainWindow::setWindowMinimumSizes(int min_width,int min_height)
{
this->min_width = min_width;
this->min_height = min_height;
}
void MainWindow::setWindowMaximumSizes(int max_width,int max_height)
{
this->max_width = max_width;
this->max_height = max_height;
}void MainWindow::createActions()
{
HelloTestAct = new QAction(tr("&HelloTest"),this);
connect(HelloTestAct,SIGNAL(triggered()),this,SLOT(Launch_Hello_Test()));}
void MainWindow::Launch_Hello_Test()
{qDebug() << "Launch_Hello_Test"; ApplicationProcess = new QProcess(display); QString executable(HELLOTEST); QStringList arguments; arguments << QString::number(display->winId()); ApplicationProcess->start(executable, arguments);
}
void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(HelloTestAct);
}MainWindow :: ~MainWindow()
{
}@
mainwindow.h@#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QDialog>
#include <QtGui>
#include <qwidget.h>
#include <QProcess>
#include <QString>
#include "applicationwindow.h"class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget parent = 0);
~MainWindow();
private:
QProcess ApplicationProcess;
int max_width;
int max_height;
int min_width;
int min_height;QMenu *fileMenu;
QWidget* mainwindow;
ApplicationWindow* appwindow;
QHBoxLayout* mainLayout;
QVBoxLayout* vLayout;
QWidget* vWidget;
QX11EmbedContainer* display;
QAction* HelloTestAct;
private:
void createActions();
void createMenus();
void getDisplayProperties(int* width,int* height);
void setWindowMinimumSizes(int min_width,int min_height);
void setWindowMaximumSizes(int min_width,int max_width);private slots:
void Launch_Hello_Test();
};#endif // MAINWINDOW_H
@ -
following is the sample app, it does not do much , just go and sit in one container.
hellotest.cpp
@#include "hellotest.h"
HelloTest :: HelloTest(QWidget *parent):
QWidget(parent)
{qDebug() << "in hello test"; QWidget *window = new QWidget(parent); QVBoxLayout *vl = new QVBoxLayout; window -> resize(500,500); window -> setPalette(QPalette(QColor(0,255,0,255))); window -> setAutoFillBackground(true); this -> setLayout(vl); vl -> addWidget(window);
}
HelloTest::~HelloTest()
{}
@
hellotest.h
@#ifndef HELLOTEST_H
#define HELLOTEST_H#include <QWidget>
#include <QDebug>
#include <QX11EmbedWidget>
#include <QApplication>
#include <QVBoxLayout>
#include <QDebug>class HelloTest :public QWidget
{
Q_OBJECTpublic: HelloTest(QWidget *parent = 0); ~HelloTest(); private:
};
#endif // HELLOTEST_H
@
main.cpp
@#include "hellotest.h"
QX11EmbedWidget *embed;
HelloTest *hellotest;int main(int argc, char argv[])
{
QApplication qapp(argc, argv);
QString windowId(qapp.arguments()[1]);
QVBoxLayout layout = new QVBoxLayout;embed = new QX11EmbedWidget; embed -> setMinimumSize(500,500); embed -> setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); embed -> setPalette(QColor(255,0,0,255)); embed -> setAutoFillBackground(true); hellotest = new HelloTest(embed); hellotest -> setContentsMargins(0,0,0,0); if(NULL == embed) { qDebug() << "Unable to create hellotest"; return 0; } if(argc < 2) { qDebug() << "More Arguments Needed"; return 0; } qDebug()<<"windowId in WG:"<<windowId; layout -> addWidget(hellotest); embed -> setLayout(layout); embed -> embedInto(windowId.toULong()); embed -> show(); return qapp.exec();
}@
-
[quote author="JKSH" date="1381286709"]Hmm... that sounds like a bug, either in Qt or your code.[/quote]
Thats is really what i want to know,
[quote author="JKSH" date="1381286709"]Can you give more details on when your embedding succeeds, and when it fails?[/quote]
Its random, out of 10 trials some times 8, 5 , 3 , 1, none.
[quote author="JKSH" date="1381286709"]
QWidget::createWindowContainer() converts a QWindow into a QWidget. After you convert, you can add it to another widget's layout.
[/quote]i tried this i will let you know by example in a while,
kindly go through my Qt5 example code[quote author="JKSH" date="1381286709"]
What do you mean? Is it more work than QX11EmbedWidget?[/quote]
I am quite new here, it may be done in other way.
for QWindow to function properly so may functions are created
for example in the raster example provided with QtQBackingStore is used and then functions likes event,renderLater, resizeEvent,exposeEvent, paintDevice and QPainter, ...etc.. etc...
-
[quote author="Dcqt" date="1381297578"]
[quote author="JKSH" date="1381286709"]Can you give more details on when your embedding succeeds, and when it fails?[/quote]Its random, out of 10 trials some times 8, 5 , 3 , 1, none.[/quote]Do these trials use the same winIds all the time?
[quote author="Dcqt" date="1381297578"][quote author="JKSH" date="1381286709"]
QWidget::createWindowContainer() converts a QWindow into a QWidget. After you convert, you can add it to another widget's layout.
[/quote]i tried this i will let you know by example in a while[/quote]Have you tried this yet? What did you get?
It should be straightforward:
@
QVBoxLayout* layout = ...QWindow* myWindow = QWindow::fromWinId(id);
QWidget* myWidget = QWidget::createWindowContainer(myWindow);
layout->addWidget(myWidget);
@[quote author="Dcqt" date="1381297578"]kindly go through my Qt5 example code[/quote]It's quite long and hard to read. Please post minimal examples. You should remove parts that aren't related to your problem, like setting size/palette/background/margins/menus/etc.
[quote author="Dcqt" date="1381297578"]for QWindow to function properly so may functions are created
for example in the raster example provided with QtQBackingStore is used and then functions likes event,renderLater, resizeEvent,exposeEvent, paintDevice and QPainter, ...etc.. etc...[/quote]You use those functions only if you want to paint the window yourself. Since you want to embed an external window, you don't need to paint anything. The external window already paints itself.
-
[quote author="JKSH" date="1381385832"]Do these trials use the same winIds all the time?
[/quote]
No the winIds are different for each run.[quote author="JKSH" date="1381286709"]Have you tried this yet? What did you get?
It should be straightforward:
[/quote]
Yes you are right i tried the same way , i tried to add a webview to the display(QWidget), but its not getting added.
and in the log i am getting belowbq. LEAK: 3 RenderObject
LEAK: 1 Page
LEAK: 1 Frame
LEAK: 4 WebCoreNode@
QWidget * display = new QWidget;
QWidget * window ;void MainWindow::launch_app(int id)
{
WId winid = (WId) id;
qDebug()<<"In launch_app win id is "<< id;
QVBoxLayout *vl = new QVBoxLayout;
display->setLayout(vl);
window = createWindowContainer(QWindow::fromWinId(winid),display,
Qt::WindowMinMaxButtonsHint|Qt::WindowCloseButtonHint
|Qt::WindowCancelButtonHint
|Qt::FramelessWindowHint);QUrl qurl("http://google.com"); QHBoxLayout *layout2 = new QHBoxLayout; QWebView *m_WebView = new QWebView; window->setLayout(layout2); layout2->addWidget(m_WebView); m_WebView->setFocusPolicy(Qt::StrongFocus); m_WebView->load(qurl); m_WebView->show(); vl -> addWidget(window); qDebug()<<"addWidget";
}
@[quote author="JKSH" date="1381385832"] It's quite long and hard to read. Please post minimal examples. You should remove parts that aren't related to your problem, like setting size/palette/background/margins/menus/etc.[/quote]
Sorry , i will clean up and post new.
[quote author="JKSH" date="1381385832"] You use those functions only if you want to paint the window yourself. Since you want to embed an external window, you don't need to paint anything. The external window already paints itself.[/quote]
I removed all those painting and events and every thing now the raster class only have this
@class RasterWindow : public QWindow
{
Q_OBJECT
public:
explicit RasterWindow(QWindow *parent = 0);
};
@then i tried this but nothing shown up on my widget.
@window = createWindowContainer(QWindow::fromWinId(winid),display,
Qt::WindowMinMaxButtonsHint|Qt::WindowCloseButtonHint
|Qt::WindowCancelButtonHint
|Qt::FramelessWindowHint);window->setPalette(QPalette(QColor(255,0,0,255))); window->setAutoFillBackground(1);@
-
I will follow with current discussion going on here , but i also want to explain you the problem clearly as i am getting some hope that i can solve problem with your help.
I have a mainwindow from which i launch the applications using QProcees by passing the window id.
@QX11EmbedContainer* Container;
QStringList arguments;
ApplicationProcess = new QProcess(Container);
arguments << QString::number(Container->winId());
ApplicationProcess->start(executable, arguments);@The window id i am passing is of "Container", this is layed out on mainwindow.
now i have several applications which have following code in their main.
@ QString winId(qapp.arguments()[2]);
embwdgt = new QX11EmbedWidget;
embwdgt -> setLayout(layout);// to have other widgets on it
embwdgt -> embedInto(winId.toULong());
embwdgt -> show();@and some other applications use
@gst_x_overlay_set_window_handle(GST_X_OVERLAY(sink),windowID);@
this approach works well on Qt 4.8, but not on Qt 5.0 because of following reason.
Qt 5.0 does not have QX11EmbedContainer and QX11EmbedWidget.now i need to find the equivalent of QX11EmbedContainer and QX11EmbedWidget in Qt 5 or use some other mechanism
which have the same effect.i am not sure how big the modification will be, becasue i dont know a way yet.
createWindowContainer and QWindow are available in Qt 5.1 but not available in Qt 5.0
if i have to use Qt 5.0 i wont be able to use createWindowContainer and QWindow also.
thus gives us three questions,
is it possible to have embed widgets in Qt 5.0, if so, how?
if Qt 5.1 is the only way , then i need a small working example for embedding widgets?
is there any other way by which we can embed widgets (through x11 or xcb interface)? -
By the way, what OS are you running? Is it in a native machine, or virtual machine?
Remember the differences:
- In Qt 4, you give the CONTAINER's WinID to the client. Then, the client embeds itself into the container.
- In Qt 5, you give the CLIENT's WinID to QWindow::fromWinId(). This function does two things at the same time: (1) Create a container, and (2) Embed the client into the container.
Here is how you should do it:
@
// This is your client widget
QWidget* client = new QWidget();// Add buttons, labels, etc. to your client
client->setLayout(...);// Get your client's WinID
WId clientId = client->winId();// This is your container, with the client ALREADY embedded inside
QWindow* container = QWindow::fromWinId(clientId);// Show your container, with the client embedded inside.
container->show();
@If you want your container to be a QWidget instead of a QWindow, then:
@
QWidget* client = new QWidget();
client->setLayout(...);
WId clientId = client->winId();// This is your container, with the client ALREADY embedded inside
QWidget* container = QWidget::createWindowContainer(QWindow::fromWinId(clientId));
container->show();
@[quote author="Dcqt" date="1381398640"]
@
window = createWindowContainer(QWindow::fromWinId(winid));
window->setLayout(layout2);
@
[/quote]Here, winid is your client's WinID. window is your container widget with the client embedded inside.If you have a normal widget, widget->setLayout() will remove the existing layout in the widget (which might be why you don't see anything). However, I don't think layouts can even be applied to a container widget.
You should add your container to a layout. You should not add a layout to your container:
@
// Don't show your containerQVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(container);
layout->addWidget(webView);QWidget *bigWidget = new QWidget();
bigWidget->setLayout(layout);
bigWidget->show();
@[quote]is it possible to have embed widgets in Qt 5.0, if so, how?[/quote]No, sorry. The functionality was only added in Qt 5.1.
[quote]is there any other way by which we can embed widgets (through x11 or xcb interface)?[/quote]I haven't seen any other way.
-
[quote author="JKSH" date="1381426867"]By the way, what OS are you running? Is it in a native machine, or virtual machine?
[/quote]I am using a native machine with ubuntu oneric.
[quote author="JKSH" date="1381426867"]
Remember the differences:- In Qt 5, you use the CLIENT's WinID to QWindow::fromWinId(). This function does two things at the same time: (1) Create a container, and (2) Embed the client into the container.
[/quote]
I was not aware of this,thanks a lot again.
the samples i will check tomorrow and let you know if i have any issue
i dont have setup @ home :( - In Qt 5, you use the CLIENT's WinID to QWindow::fromWinId(). This function does two things at the same time: (1) Create a container, and (2) Embed the client into the container.