Qt5中QX11EmbedWidget的对应部分是什么?

时间:2016-08-05 21:54:13

标签: c++ qt5 x11 gtk3 qx11embedcontainer

在Qt4中,我们可以使用embedInto类的QX11EmbedWidget方法将任何QWidget嵌入到另一个应用程序中。但是在Qt5中,QX11EmbedWidget类被删除了。我已经在谷歌搜索了好几个小时,但我发现所有人都表示要使用QWidget::createWindowContainer方法。但是,据我所知,这种方法只是QX11EmbedContainer的替代。

所以问题是:我们如何将Qt5-Widget嵌入非Qt窗口? - 如果是metters:非Qt窗口是Gtk3。

我已经被要求提供用例,所以让我简要说明一下:考虑一个基于Gtk的应用程序,您愿意扩展它 - 以及UI组件你需要的,已经存在,但用Qt编写。目标是避免将应用程序移植到Qt或将组件移植到Gtk。

2 个答案:

答案 0 :(得分:3)

我最初的方法是从Qt端请求嵌入。我没有运气,因为我在Qt5中找不到QX11EmbedWidget::embedInto的任何等价物。放弃这一点后,我决定尝试XReparentWindowreportedly used with success。但是,由于缺乏文档,我无法重现这一点。我的第三次尝试是从服务器侧启动嵌入,这是我案例中的Gtk窗口。我很高兴地报告,它有效: - )

对于记录:如何将任意Qt5小部件嵌入到Gtk窗口中

TL; DR:

  1. 确保在与Qt部分分开的单元中编写Gtk代码。这是必要的,以避免Qt5和Gtk3之间的名称冲突。
  2. 只需使用gtk_socket_add_id将任何X11窗口嵌入GtkSocket
  3. 另请参阅the documentation以供参考,但请注意,给出它们的示例甚至无法编译,因为它们忘记了GTK_SOCKET宏。相反,以下代码可以

    proof

    详细信息

    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)

试试这个:

http://qt-project.org/doc/qt-5.1/qtx11extras/qx11info.html