2013-07-02 2 views
1

Я хочу сохранить буфер textview в формате pdf. Я могу сделать это с помощью reportlab, если это просто простой текст. Но что, если я хочу сохранить все, от текста с его тегами, а также изображения?Как сохранить содержимое текста в gtk в pdf с помощью python?

from gi.repository import Gtk, GdkPixbuf 
import pango 
from reportlab.pdfgen import canvas 

class gui(): 
    def __init__(self): 
     self.window = Gtk.Window() 
     self.window.connect('delete-event', Gtk.main_quit) 

     self.box = Gtk.Box() 
     self.window.add(self.box) 

     self.textview = Gtk.TextView() 
     self.textbuffer = self.textview.get_buffer() 

     self.tag_bold = self.textbuffer.create_tag("bold", 
                weight=pango.WEIGHT_BOLD) 
     self.tag_italic = self.textbuffer.create_tag("italic", 
                style=pango.STYLE_ITALIC) 

     pix = GdkPixbuf.Pixbuf.new_from_file_at_size('baby.jpg', 50, 50) 

     tag = [self.tag_bold, 
       self.tag_italic] 

     self.textbuffer.insert_pixbuf(self.textbuffer.get_end_iter(), pix) 
     for i in range(20): 
      self.textbuffer.insert_with_tags(self.textbuffer.get_end_iter(), 
                'line%d\n' % (i+1), 
                tag[i % 2]) 

     self.box.pack_start(self.textview, True, True, 0) 

     self.button = Gtk.Button(label='Start') 
     self.button.connect('clicked', self.on_button_clicked) 
     self.box.pack_start(self.button, True, True, 0) 

     self.window.show_all() 
     Gtk.main() 

    def on_button_clicked(self, widget): 
     canv = canvas.Canvas('tes.pdf') 

     for i in range(self.textbuffer.get_line_count()): 
      a = self.textbuffer.get_iter_at_line(i) 
      b = self.textbuffer.get_iter_at_line(i+1).get_offset() 
      c = self.textbuffer.get_iter_at_offset(b - 1) 
      t = self.textbuffer.get_text(a, b, True) 
      line = 750 - (15 * l) 
      canv.drawString(40, line, t) 

     canv.save() 

if __name__ == '__main__': 
    gui = gui() 

EDIT: drahnr предлагает использовать вместо Каира. Хорошо, я думаю, что это лучшая идея, так как reportlab координирует начало с нижнего левого угла и начало координат cairo слева вверху. Ниже мой код, используя cairo.

from gi.repository import Gtk, GdkPixbuf, Gdk 
import pango 
import cairo 


class gui(): 
    def __init__(self): 
     self.window = Gtk.Window() 
     self.window.connect('delete-event', Gtk.main_quit) 
     self.textview = Gtk.TextView() 
     self.window.add(self.textview) 

     self.initText() 
     self.createPDF() 

     self.window.show_all() 
     Gtk.main() 

    def initText(self): 
     self.tag_bold = self.textview.get_buffer().create_tag("bold", weight=pango.WEIGHT_BOLD) 
     self.tag_italic = self.textview.get_buffer().create_tag("italic", style=pango.STYLE_ITALIC) 

     pix = GdkPixbuf.Pixbuf.new_from_file_at_size('baby.png', 50, 50) 

     tag = [self.tag_bold, self.tag_italic] 

     self.textview.get_buffer().insert_pixbuf(self.textview.get_buffer().get_end_iter(), pix) 
     self.textview.get_buffer().insert(self.textview.get_buffer().get_end_iter(), '\n') 
     for i in range(20): 
      self.textview.get_buffer().insert_with_tags(self.textview.get_buffer().get_end_iter(), 'line%d' % (i+1), tag[i % 2]) 
      self.textview.get_buffer().insert(self.textview.get_buffer().get_end_iter(), '\n') 

    def createPDF(self): 
     line = 30 
     row = 5 
     pos = 0 
     ps = cairo.PDFSurface('tes.pdf', 600, 770) 
     cr = cairo.Context(ps) 

     while pos != self.textview.get_buffer().get_end_iter().get_offset(): 
      if self.textview.get_buffer().get_iter_at_offset(pos).has_tag(self.tag_bold): 
       cr.select_font_face('Times', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) 
      elif self.textview.get_buffer().get_iter_at_offset(pos).has_tag(self.tag_italic): 
       cr.select_font_face('Times', cairo.FONT_SLANT_ITALIC, cairo.FONT_WEIGHT_NORMAL) 
      else: 
       cr.select_font_face('Times', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) 

      t = self.textview.get_buffer().get_slice(self.textview.get_buffer().get_iter_at_offset(pos), self.textview.get_buffer().get_iter_at_offset(pos+1), False) 
      if t == '\n': 
       line += 12 
       row = 5 
      elif t == unichr(0xFFFC): 
       pix = self.textview.get_buffer().get_iter_at_offset(pos).get_pixbuf() 
       Gdk.cairo_set_source_pixbuf(cr, pix, 8 * row, line) 
       line += pix.get_width() 
       cr.paint() 
      else: 
       cr.move_to(8 * row, line) 
       cr.show_text(t) 

      pos=pos+1 
      row += 1 

if __name__ == '__main__': 
    gui() 

буквально он все тот же. Я должен сделать это, чтобы все рисовать. и drahnr предлагают использовать gtk_widget_draw, чтобы отобразить его на поверхности каира.

+0

Посмотрите на http://www.joachim-breitner.de/blog/archives/494-Better-PDF-screenshots-with-gtk-3.html – user4815162342

+0

Извините, не могли бы вы объяснить, что он сделал? Я совсем не понимаю. – user2435611

+0

Я не вижу, как привязана ссылка @ user4815162342, и если это так, мне кажется, это требует еще большего объяснения. –

ответ

0

Это не питон ответ, но это может быть применимо к вашей проблеме тоже:

Rendering к cairo_surface_t и использовать PDF поверхности API - как сделать ваш текст к вам, простой способ будет для визуализации текста через gtk_widget_draw полностью.

https://developer.gnome.org/gtk3/stable/GtkWidget.html#gtk-widget-draw. http://cairographics.org/manual/cairo-PDF-Surfaces.html

Update # 2:

Ниже неполно и требует виджета, который делает рендеринг для вас, и, таким образом, не заменяет gtk_widget_draw вызова. Вам нужно создать расширение ctype или сделать чертеж вручную.

Источник: http://www.stuartaxon.com/2010/02/03/using-cairo-to-generate-svg-in-django/

Update # 1:

Эта функция делает изображение на поверхность (PDF, SVG, независимо от ваших скомпилированных библиотек каира поддерживает) и сохраняет его в файл dest - для Подробную информацию смотрите в руководстве по эксплуатации конкретной функции

def draw_render_to_file(dest, Widget, Surface = PDFSurface, width = 100, height = 100) 
    widget = Widget(Surface) 
    surface = widget.Surface(dest, width, height) 
    widget.draw(Context(surface), width, height) 
    surface.finish() 
+0

@ user4815162342 обновленный ответ – drahnr

+0

Мне все еще не удалось это сделать. У вас есть хороший учебник для Gtk.Widget.draw()? – user2435611

+0

@ user2435611 вы никогда не вызываете процедуру gtk_widget_draw, которая является членом вашего виджета (здесь: TextView). Также распространенной ошибкой является аргумент, передаваемый в python (я не проверял ваши аргументы, это ваша задача) – drahnr

 Смежные вопросы

  • Нет связанных вопросов^_^