Qt5 中 QX11EmbedWidget 的对应物是什么?
What's the counterpart of QX11EmbedWidget in Qt5?
在 Qt4 中,我们可以使用 QX11EmbedWidget
class 的 embedInto
方法将任何 QWidget
嵌入到另一个应用程序中。但是在 Qt5 中, QX11EmbedWidget
class 被删除了。我已经搜索 Google 好几个小时了,但我发现的所有内容都表明要改用 QWidget::createWindowContainer
方法。但是,据我了解,此方法是 QX11EmbedContainer
.
的替代方法
所以问题来了:我们如何将 Qt5-Widget 嵌入非 Qt window? -
以防万一:非 Qt window 是 Gtk3.
有人问我用例,所以让我简要说明一下:考虑一个基于 Gtk 的应用程序,您愿意扩展它- 而您需要的 UI 组件已经存在,但是是用 Qt 编写的。目标是避免将应用程序移植到 Qt 或将组件移植到 Gtk。
引用此link:
https://forum.qt.io/topic/32785/qwindow-qwidget-qt5-x11embedding-how/2
All the x11 stuff has moved to the "extras" department found on
Gitorious. (QX11EmbedWidgets and QX11EmbedContainer and the likes are
not in 5.x)
试试这个:
我最初的方法是从 Qt 端请求嵌入。我运气不好,因为我在 Qt5 中找不到 QX11EmbedWidget::embedInto
的任何等价物。放弃之后,我决定尝试XReparentWindow
,结果是reportedly used with success。但是,由于缺少文档,我无法重现这一点。我的第三次尝试是从 server 端启动嵌入,在我的例子中是 Gtk window。我很高兴地报告,它有效:-)
备案:如何将任意 Qt5 小部件嵌入 Gtk window
长话短说:
- 确保在与 Qt 部分分开的单元中编写 Gtk 代码。这是必要的,以避免 Qt5 和 Gtk3 之间的名称冲突。
- 只需使用
gtk_socket_add_id
将任何 X11 window 嵌入 GtkSocket
.
另见 the documentation 以供参考,但请注意,给出的示例甚至无法编译,因为他们忘记了 GTK_SOCKET
宏。相反,下面的代码有效.
详情
QGtkWindow
class 提供了 Gtk 接口 window。
class QGtkWindow : public QObject
{
public:
QGtkWindow();
virtual ~QGtkWindow();
void setCentralWidget( QWidget* const widget );
void show();
private:
GtkWindowAdapter gtkWindow;
QWidget* const container;
}; // QGtkWindow
GtkWindowAdapter
class 包装 Gtk 调用并将它们与应用程序的 Qt 部分隔离。这个 class 的对象代表 Gtk window.
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 window:
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 );
}
您可能已经注意到此 class 提供的 embed
方法。此方法启动任何 X11 window 的嵌入。 show
方法使封装的 Gtk window 可见。
void GtkWindowAdapter::embed( unsigned long clientWinId )
{
gtk_socket_add_id( GTK_SOCKET( pimpl->socket ), clientWinId );
}
void GtkWindowAdapter::show()
{
gtk_widget_show( pimpl->widget );
}
现在,QGtkWindow
class 的实现相当简单。创建时,它使用 GtkWindowApdater
初始化 Gtk window 并将空 QWidget
放入 window:
QGtkWindow::QGtkWindow()
: container( new QWidget() )
{
container->setLayout( new QVBoxLayout() );
gtkWindow.embed( container->winId() );
container->show();
}
当 QGtkWindow
class 的用户决定将一些小部件放入 window 时,setCentralWidget
是可行的方法。它只是清除了最初嵌入到 Gtk window 中的父窗口小部件,然后插入用户的窗口小部件:
void QGtkWindow::setCentralWidget( QWidget* const widget )
{
qDeleteAll( pimpl->container->layout()->children() );
pimpl->container->layout()->addWidget( widget );
}
void QGtkWindow::show()
{
pimpl->gtkWindow.show();
}
希望这可以节省一些时间。
在 Qt4 中,我们可以使用 QX11EmbedWidget
class 的 embedInto
方法将任何 QWidget
嵌入到另一个应用程序中。但是在 Qt5 中, QX11EmbedWidget
class 被删除了。我已经搜索 Google 好几个小时了,但我发现的所有内容都表明要改用 QWidget::createWindowContainer
方法。但是,据我了解,此方法是 QX11EmbedContainer
.
所以问题来了:我们如何将 Qt5-Widget 嵌入非 Qt window? - 以防万一:非 Qt window 是 Gtk3.
有人问我用例,所以让我简要说明一下:考虑一个基于 Gtk 的应用程序,您愿意扩展它- 而您需要的 UI 组件已经存在,但是是用 Qt 编写的。目标是避免将应用程序移植到 Qt 或将组件移植到 Gtk。
引用此link:
https://forum.qt.io/topic/32785/qwindow-qwidget-qt5-x11embedding-how/2
All the x11 stuff has moved to the "extras" department found on Gitorious. (QX11EmbedWidgets and QX11EmbedContainer and the likes are not in 5.x)
试试这个:
我最初的方法是从 Qt 端请求嵌入。我运气不好,因为我在 Qt5 中找不到 QX11EmbedWidget::embedInto
的任何等价物。放弃之后,我决定尝试XReparentWindow
,结果是reportedly used with success。但是,由于缺少文档,我无法重现这一点。我的第三次尝试是从 server 端启动嵌入,在我的例子中是 Gtk window。我很高兴地报告,它有效:-)
备案:如何将任意 Qt5 小部件嵌入 Gtk window
长话短说:
- 确保在与 Qt 部分分开的单元中编写 Gtk 代码。这是必要的,以避免 Qt5 和 Gtk3 之间的名称冲突。
- 只需使用
gtk_socket_add_id
将任何 X11 window 嵌入GtkSocket
.
另见 the documentation 以供参考,但请注意,给出的示例甚至无法编译,因为他们忘记了 GTK_SOCKET
宏。相反,下面的代码有效.
详情
QGtkWindow
class 提供了 Gtk 接口 window。
class QGtkWindow : public QObject
{
public:
QGtkWindow();
virtual ~QGtkWindow();
void setCentralWidget( QWidget* const widget );
void show();
private:
GtkWindowAdapter gtkWindow;
QWidget* const container;
}; // QGtkWindow
GtkWindowAdapter
class 包装 Gtk 调用并将它们与应用程序的 Qt 部分隔离。这个 class 的对象代表 Gtk window.
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 window:
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 );
}
您可能已经注意到此 class 提供的 embed
方法。此方法启动任何 X11 window 的嵌入。 show
方法使封装的 Gtk window 可见。
void GtkWindowAdapter::embed( unsigned long clientWinId )
{
gtk_socket_add_id( GTK_SOCKET( pimpl->socket ), clientWinId );
}
void GtkWindowAdapter::show()
{
gtk_widget_show( pimpl->widget );
}
现在,QGtkWindow
class 的实现相当简单。创建时,它使用 GtkWindowApdater
初始化 Gtk window 并将空 QWidget
放入 window:
QGtkWindow::QGtkWindow()
: container( new QWidget() )
{
container->setLayout( new QVBoxLayout() );
gtkWindow.embed( container->winId() );
container->show();
}
当 QGtkWindow
class 的用户决定将一些小部件放入 window 时,setCentralWidget
是可行的方法。它只是清除了最初嵌入到 Gtk window 中的父窗口小部件,然后插入用户的窗口小部件:
void QGtkWindow::setCentralWidget( QWidget* const widget )
{
qDeleteAll( pimpl->container->layout()->children() );
pimpl->container->layout()->addWidget( widget );
}
void QGtkWindow::show()
{
pimpl->gtkWindow.show();
}
希望这可以节省一些时间。