Попытка отобразить окно GTK+ в изображение

GTK использует cairo для рисования. Итак, я пытаюсь создать приложение hello world, которое записывает изображение (svg, png,...) вместо X11. Я столкнулся с двумя проблемами: - Изображение пусто - При запуске без запущенного X11 (что является фактической целью) я получаю сообщение об ошибке "** (a.out:9021): ПРЕДУПРЕЖДЕНИЕ **: Не удалось открыть X-дисплей"

Кодекс является черновиком!

#include <string>
#include <iostream>
#include <thread>
#include <chrono>
#include <cmath>

#include <cairo.h>
#include <cairommconfig.h>
#include <cairomm/context.h>
#include <cairomm/surface.h>
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

int main(int argc, char *argv[])
{

  gtk_init(&argc, &argv);
  GtkWidget *window;
  GtkWidget *button;
   //   GtkWidget *main_window = gtk_initialize();

  window = gtk_offscreen_window_new();

  button = gtk_button_new_with_label ("Hello World");
  gtk_container_add (GTK_CONTAINER (window), button);
  gtk_widget_show  (window);
  GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
  std::cout << "gdk window: " << gdk_window << std::endl;
  cairo_surface_t * surfp =  gdk_offscreen_window_get_surface(gdk_window);
  std::cout << "Created Window will now draw to png" << std::endl;

  std::string filename = "image.svg";
  double width = 600;
  double height = 400;

  Cairo::SvgSurface srfobj(surfp);

  Cairo::RefPtr<Cairo::SvgSurface> refptr(&srfobj);

  Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(refptr);

  cr->save(); // save the state of the context
  cr->show_page();

  std::cout << "Wrote SVG file \"" << filename << "\"" << std::endl;
  std::chrono::milliseconds dura( 200 );
  std::this_thread::sleep_for(dura);

  return 0;
}
  • Почему этот код не работает?
  • Могу ли я запустить приложение gtk без запущенного X11, или я должен просто игнорировать предупреждение?

person JDel    schedule 17.01.2014    source источник
comment
Возможно, связано: stackoverflow.com/questions/4944441/   -  person drahnr    schedule 17.01.2014


Ответы (3)


Вот мое решение, основанное на вашем примере кода - имейте в виду, что это грязное решение и может не работать с более новыми версиями GTK3. Он работает для сохранения пользовательского интерфейса окна (проверено только с одной кнопкой), но все же требует (где-то) работающий X-сервер. Он также игнорирует / не использует ваши настройки размера изображения - вам придется изменить его размер по своему усмотрению. Я не знаю, можно ли (и как) обрезать эту строку (X-Server // X-Framebuffer) (DirectFB, похоже, больше не поддерживается), но...

Развлекайся!

// Default
#include <string>
#include <iostream>
#include <thread>
#include <chrono>

// cairo / cairomm / gtk
#include <cairo.h>
#include <cairomm/context.h> //libcairomm-1.0-dev
#include <gtk/gtk.h>

int main(int argc, char *argv[]) {
    // Init
    gtk_init(&argc, &argv);

    // Create window with a button
    GtkWidget *window;
    GtkWidget *button;

    window = gtk_offscreen_window_new();
    button = gtk_button_new_with_label("Hello World");
    gtk_container_add(GTK_CONTAINER(window), button);
    gtk_widget_show_all(window);

    // Make a gdk window out of it, prepare cairo and draw it to it
    GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
    cairo_surface_t* surfp = gdk_offscreen_window_get_surface(gdk_window);
    cairo_t* context = cairo_create(surfp);
    gtk_widget_draw(GTK_WIDGET(window), context);

    // Yay - begin the dump!
    Cairo::SvgSurface srfobj(surfp);
    std::string filename = "image.png";
    srfobj.write_to_png(filename);
    std::cout << "Done." << std::endl;

    // Aaand a little sleep...
    std::chrono::milliseconds dura(1000);
    std::this_thread::sleep_for(dura);

    return 0;
}
person Simonmicro    schedule 18.06.2019


Ответ на оба ваших вопроса заключается в том, что вы не можете запускать приложения GTK+ без какого-либо вывода. Вы используете gtk-x11, для которого требуется XServer. Возможно, вам повезет с бэкендом DirectFB, но я бы не стал задерживать дыхание, так как не знаю, поддерживается ли он вообще.

Так как Gtk не работает без XServer, результирующий образ будет пустым.

person iain    schedule 20.01.2014