Что является аналогом QX11EmbedWidget в Qt5?

В Qt4 мы могли бы использовать embedInto метод QX11EmbedWidget класс для встраивания любого QWidget в другое приложение. Но в Qt5 QX11EmbedWidget класс был исключен. Я искал в Google много часов, но все, что я нашел, указывало на использование QWidget::createWindowContainer метод вместо. Однако, насколько я понимаю, этот метод является скорее заменой QX11EmbedContainer,

Итак, вот вопрос: как мы встраиваем Qt5-Widget в не-Qt окно? - И в случае, если это встречается: окном, не являющимся Qt, является Gtk3.


Меня попросили описать вариант использования, поэтому позвольте мне вкратце проиллюстрировать: рассмотрим приложение на основе Gtk, которое вы готовы расширить - и компонент UI, который вам нужен, уже существует, но написан на Qt. Цель состоит в том, чтобы избежать портирования приложения на Qt или компонента на Gtk.

2 ответа

Решение

Мой первоначальный подход состоял в том, чтобы запросить встраивание со стороны Qt. Мне не повезло с этим, так как я не мог найти эквивалент для QX11EmbedWidget::embedInto в Qt5. Отказавшись от этого, я решил дать XReparentWindow попытка, которая, как сообщается, была использована с успехом. Однако из-за отсутствия документации я не смог воспроизвести это. Моей третьей попыткой было инициировать встраивание со стороны сервера, в моем случае это окно Gtk. Я рад сообщить, что это сработало:-)


Для записи: Как встроить произвольный виджет Qt5 в окно Gtk

TL;DR:

  1. Убедитесь, что вы пишете свой код Gtk в модуле, отдельном от части Qt. Это необходимо для того, чтобы избежать конфликтов имен между Qt5 и Gtk3.
  2. Просто использовать gtk_socket_add_id встроить любое окно X11 в GtkSocket,

Также смотрите документацию для справки, но обратите внимание, что приведенный пример даже не компилируется, потому что они забыли 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 класс довольно прост. После создания он инициализирует окно Gtk, используя GtkWindowApdater и кладет пустой 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();
}

Надеюсь, это может сэкономить кому-то много часов.

Цитировать по этой ссылке:

https://forum.qt.io/topic/32785/qwindow-qwidget-qt5-x11embedding-how/2

Все материалы по x11 были перенесены в отдел "extras", найденный в Gitorious. (QX11EmbedWidgets и QX11EmbedContainer и им подобные не в 5.x)

Попробуй это:

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

Другие вопросы по тегам