在Qt4中,我们可以使用embedInto
类的QX11EmbedWidget
方法将任何QWidget
嵌入到另一个应用程序中。但是在Qt5中,QX11EmbedWidget
类被删除了。我已经在谷歌搜索了好几个小时,但我发现所有人都表示要使用QWidget::createWindowContainer
方法。但是,据我所知,这种方法只是QX11EmbedContainer
的替代。
所以问题是:我们如何将Qt5-Widget嵌入非Qt窗口? - 如果是metters:非Qt窗口是Gtk3。
我已经被要求提供用例,所以让我简要说明一下:考虑一个基于Gtk的应用程序,您愿意扩展它 - 以及UI组件你需要的,已经存在,但用Qt编写。目标是避免将应用程序移植到Qt或将组件移植到Gtk。
答案 0 :(得分:3)
我最初的方法是从Qt端请求嵌入。我没有运气,因为我在Qt5中找不到QX11EmbedWidget::embedInto
的任何等价物。放弃这一点后,我决定尝试XReparentWindow
,reportedly used with success。但是,由于缺乏文档,我无法重现这一点。我的第三次尝试是从服务器侧启动嵌入,这是我案例中的Gtk窗口。我很高兴地报告,它有效: - )
gtk_socket_add_id
将任何X11窗口嵌入GtkSocket
。另请参阅the documentation以供参考,但请注意,给出它们的示例甚至无法编译,因为它们忘记了GTK_SOCKET
宏。相反,以下代码可以。
QGtkWindow
类提供了Gtk窗口的接口。
class QGtkWindow : public QObject
{
public:
QGtkWindow();
virtual ~QGtkWindow();
void setCentralWidget( QWidget* const widget );
void show();
private:
GtkWindowAdapter gtkWindow;
QWidget* const container;
}; // QGtkWindow
GtkWindowAdapter
类包装Gtk调用并将它们与应用程序的Qt部分隔离开来。此类的对象表示Gtk窗口。
class GtkWindowAdapter
{
public:
GtkWindowAdapter();
~GtkWindowAdapter();
void show();
void embed( unsigned long clientWinId );
private:
struct Details;
const std::auto_ptr< Details > pimpl;
}; // GtkWindowAdapter
实例化时,GtkWindowAdapter
对象首先初始化Gtk,
static bool gtkInitialized = false;
struct GtkWindowAdapter::Details
{
GtkWidget* widget;
GtkWidget* socket;
void setupUi();
};
GtkWindowAdapter::GtkWindowAdapter()
: pimpl( new Details() )
{
if( !gtkInitialized )
{
int argc = 0;
gtk_init( &argc, NULL );
gtkInitialized = true;
}
pimpl->setupUi();
}
然后设置Gtk窗口:
void GtkWindowAdapter::Details::setupUi()
{
widget = gtk_window_new( GTK_WINDOW_TOPLEVEL );
socket = gtk_socket_new();
gtk_widget_show( socket );
gtk_container_add( GTK_CONTAINER ( widget ), socket );
gtk_widget_realize( socket );
}
您可能已经注意到此类提供的embed
方法。此方法启动任何X11窗口的嵌入。 show
方法将封装的Gtk窗口变为可见。
void GtkWindowAdapter::embed( unsigned long clientWinId )
{
gtk_socket_add_id( GTK_SOCKET( pimpl->socket ), clientWinId );
}
void GtkWindowAdapter::show()
{
gtk_widget_show( pimpl->widget );
}
现在,QGtkWindow
类的实现非常简单。创建后,它会使用GtkWindowApdater
初始化Gtk窗口,并将空QWidget
放入该窗口:
QGtkWindow::QGtkWindow()
: container( new QWidget() )
{
container->setLayout( new QVBoxLayout() );
gtkWindow.embed( container->winId() );
container->show();
}
当QGtkWindow
类的用户决定将一些小部件放入窗口时,setCentralWidget
是可行的方法。它只是清除最初嵌入Gtk窗口的父窗口小部件,然后插入用户的窗口小部件:
void QGtkWindow::setCentralWidget( QWidget* const widget )
{
qDeleteAll( pimpl->container->layout()->children() );
pimpl->container->layout()->addWidget( widget );
}
void QGtkWindow::show()
{
pimpl->gtkWindow.show();
}
希望这可能会花费很多时间。
答案 1 :(得分:1)
引用此链接:
https://forum.qt.io/topic/32785/qwindow-qwidget-qt5-x11embedding-how/2
所有x11内容已移至找到的“额外”部门 Gitorious。 (QX11EmbedWidgets和QX11EmbedContainer等都是 不在5.x)
试试这个: