I have some information (a list of participants to an event) which I want to print out easily. No need for fancy layout, just a table with several columns, and if possible a drawn line in between the lines of text for better readability. Will need to print landscape to make it all fit (can be done via a GtkPageSetup).
I'm using Python, and I'm on Linux so will have to use the GtkPrintUnixDialog interface. I've been searching on Internet but can't find any example on how this could possibly be achieved.
To simplify the problem: it's for my own use only, so known paper size (A4).
The problem that I have is basically two-fold: 1) create a properly formatted text, suitable for printing, and 2) send this to the printer.
Any suggestions on where to start? Or better, complete examples?
I search for my old print examples, but for a start:
You could write to pdf surface, and print pdf, or
put the drawing code on on_print function. Note, it does not print what you see, but what you draw on print surface. Draw the context like a regular cairo context, but a few methods are not available(don't fit in print context) while others, like new page, are added. If I find the example, I will come with a answer more self-explanatory.
Edit: find an ex:
def on_button_clicked(self, widget):
ps = Gtk.PaperSize.new_custom("cc", "cc", 210, 297, Gtk.Unit.MM)
st = Gtk.PrintSettings()
s = Gtk.PageSetup()
s.set_paper_size(ps)
s.set_bottom_margin(4.3, Gtk.Unit.MM)
s.set_left_margin(4.3, Gtk.Unit.MM)
s.set_right_margin(4.3, Gtk.Unit.MM)
s.set_top_margin(4.3, Gtk.Unit.MM)
s.set_orientation(Gtk.PageOrientation.LANDSCAPE)
# ret = Gtk.print_run_page_setup_dialog(self, s, st)
pd = Gtk.PrintOperation()
pd.set_n_pages(1)
pd.set_default_page_setup(s)
pd.connect("begin_print", self.bg)
pd.connect("draw_page", self.draw_page)
# print(ret, s, st)
pd.set_export_filename("test.pdf")
result = pd.run(Gtk.PrintOperationAction.EXPORT, None) #play with action, but for test export first; if it's ok, then action.PRINT
print (result) # handle errors etc.
# Gtk.PaperSize.free(ps) - not needed in py
the above may be on button press or whatever
def draw_page (self, operation, context, page_number):
end = self.layout.get_line_count()
cr = context.get_cairo_context()
cr.set_source_rgb(0, 0, 0)
i = 0
start = 0
start_pos = 0
iter = self.layout.get_iter()
while 1:
if i >= start:
line = iter.get_line()
print(line)
_, logical_rect = iter.get_line_extents()
# x_bearing, y_bearing, lwidth, lheight = logical_rect
baseline = iter.get_baseline()
if i == start:
start_pos = 12000 / 1024.0 # 1024.0 is float(pango.SCALE)
cr.move_to(0 / 1024.0, baseline / 1024.0 - start_pos)
PangoCairo.show_layout_line(cr, line)
i += 1
if not (i < end and iter.next_line()):
break
That's just a basic example. Note that layout is a pango layout:
self.layout = cx.create_pango_layout()
self.layout.set_width(int(w / 4 * Pango.SCALE))
self.layout.set_text(text, len(text))
num_lines = self.layout.get_line_count()
page_height = 0
self.layout.set_font_description(Pango.FontDescription("Georgia Bold 12"))
k = 0
for line in range(num_lines):
if k == 4:
self.layout.set_font_description(Pango.FontDescription("Georgia 10"))
layout_line = self.layout.get_line(line)
ink_rect, logical_rect = layout_line.get_extents()
lheight = 1200
line_height = lheight / 1024.0 # 1024.0 is float(pango.SCALE)
page_height += line_height
k += 1
print ("page_height ", page_height)
copy/paste functional example:
#!/usr/bin/python
from gi.repository import Gtk, Pango, PangoCairo
import cairo
text = '''
Text.
I have some information (a list of participants to an event) which I
want to print out easily.
No need for fancy layout,
just a table with several columns,
and if possible a drawn line in between the lines of
text for better readability.
'''
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Hello World Printing")
self.button = Gtk.Button(label="Print A Rectangle")
self.button.connect("clicked", self.on_button_clicked)
self.add(self.button)
def on_button_clicked(self, widget):
ps = Gtk.PaperSize.new_custom("cc", "cc", 210, 297, Gtk.Unit.MM)
st = Gtk.PrintSettings()
s = Gtk.PageSetup()
s.set_paper_size(ps)
s.set_bottom_margin(4.3, Gtk.Unit.MM)
s.set_left_margin(4.3, Gtk.Unit.MM)
s.set_right_margin(4.3, Gtk.Unit.MM)
s.set_top_margin(4.3, Gtk.Unit.MM)
s.set_orientation(Gtk.PageOrientation.LANDSCAPE)
# ret = Gtk.print_run_page_setup_dialog(self, s, st)
pd = Gtk.PrintOperation()
pd.set_n_pages(1)
pd.set_default_page_setup(s)
pd.connect("begin_print", self.bg)
pd.connect("draw_page", self.draw_page)
# print(ret, s, st)
pd.set_export_filename("test.pdf")
result = pd.run(Gtk.PrintOperationAction.EXPORT, None)
print (result) # handle errors etc.
# Gtk.PaperSize.free(ps)
def bg(self, op, cx):
w = cx.get_width()
h = cx.get_height()
self.layout = cx.create_pango_layout()
self.layout.set_width(int(w / 4 * Pango.SCALE))
self.layout.set_text(text, len(text))
num_lines = self.layout.get_line_count()
page_height = 0
self.layout.set_font_description(Pango.FontDescription("Georgia Bold 12"))
k = 0
for line in range(num_lines):
if k == 4:
self.layout.set_font_description(Pango.FontDescription("Georgia 10"))
layout_line = self.layout.get_line(line)
ink_rect, logical_rect = layout_line.get_extents()
# print(logical_rect, ink_rect)
# x_bearing, y_bearing, lwidth, lheight = logical_rect
lheight = 1200
line_height = lheight / 1024.0 # 1024.0 is float(pango.SCALE)
page_height += line_height
# page_height is the current location on a page.
# It adds the the line height on each pass through the loop
# Once it is greater then the height supplied by context.get_height
# it marks the line and sets the current page height back to 0
k += 1
print ("page_height ", page_height)
def box(self, w, h, x, y, cx):
w, h = int(w), int(h)
cx.set_font_size(100)
cx.set_source_rgb(0, 0, 0)
cx.rectangle(x, y, w, h)
cx.stroke()
yy = 120
cx.select_font_face("Times", 0, 1)
ex = cx.text_extents("TEGOLA ROMÂNIA SRL")[2]
cx.move_to(w / 2 - ex / 2 + x, 105 + y)
cx.show_text("TEGOLA ROMÂNIA SRL")
ex = cx.text_extents("Str. Plevnei, nr. 5, Buzău")[2]
cx.move_to(w / 2 - ex / 2 + x, 210 + y)
cx.show_text("Str. Plevnei, nr. 5, Buzău")
ex = cx.text_extents("Tel.: 0238/710.280")[2]
cx.move_to(w / 2 - ex / 2 + x, 320 + y)
cx.show_text("Tel.: 0238/710.280")
ex = cx.text_extents("Fax : 0238/710021")[2]
cx.move_to(w / 2 - ex / 2 + x, 415 + y)
cx.show_text("Fax : 0238/710021")
cx.set_font_size(90)
cx.move_to(x + 120, 520 + y)
ex = cx.text_extents("Compoziție:")[2]
cx.show_text("Compoziție:")
cx.select_font_face("Times", 0, 0)
cx.move_to(x + 125 + ex, 520 + y)
cx.show_text("Polimer bituminos, liant și")
cx.move_to(x + 5, 620 + y)
cx.show_text("material de umplutură de înaltă calitate.")
cx.move_to(x + 5, 720 + y)
cx.show_text("Nu conține gudron.")
cx.move_to(x + 5, 800 + y)
cx.select_font_face("Times", 0, 1)
ex = cx.text_extents("Instrucțiuni de utilizare:")[2]
cx.show_text("Instrucțiuni de utilizare:")
cx.select_font_face("Times", 0, 0)
cx.move_to(x + 10 + ex, 800 + y)
cx.show_text("Suprafețele se")
def draw_page1(self, operation, context, page_nr=None):
ctx = context.get_cairo_context()
w = context.get_width()
h = context.get_height()
ww, hh = int(w / 4), int(h / 2)
self.k = 0
for x in range(2):
for y in range(4):
self.box(ww, hh, y * ww, x * hh, ctx)
self.k += 1
print(ctx.get_font_matrix())
def draw_page (self, operation, context, page_number):
end = self.layout.get_line_count()
cr = context.get_cairo_context()
cr.set_source_rgb(0, 0, 0)
i = 0
start = 0
start_pos = 0
iter = self.layout.get_iter()
while 1:
if i >= start:
line = iter.get_line()
print(line)
_, logical_rect = iter.get_line_extents()
# x_bearing, y_bearing, lwidth, lheight = logical_rect
baseline = iter.get_baseline()
if i == start:
start_pos = 12000 / 1024.0 # 1024.0 is float(pango.SCALE)
cr.move_to(0 / 1024.0, baseline / 1024.0 - start_pos)
PangoCairo.show_layout_line(cr, line)
i += 1
if not (i < end and iter.next_line()):
break
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Don't forget to change action to Gtk.PrintOperationAction.PRINT for real printing.