Placing graphics & text on printed page - jan06call.jpg (0/1)

M

Michael Galvin

I am trying to use Python to send to the printer a calender filled
with a mix of text and simple graphics. I want to draw on the printed
page something like a table with 6 rows and 7 columns to represent a
calendar. I want to place text precisely within those boxes on the
printed page. I am using Python 2.4 on Windows XP

I was in the past able to do this within Visual Basic using its
printer object. Visual Basic's printer object uses a coordinate
system to allow you to draw lines and to place text on the printed
page precisely. I have attached a file "jan06call.jpg" to this message
to illustrate what I am trying to do.

Does Python have a module which would help me do this?

To put it another way, can Python control the placement of text and
graphics precisely on the printed page?

I have scoured my Python programming texts, python.org, and this
usenet group without success. Mark Lutz's wonderful book "Programming
Python" has not one reference to the word "printer" in its index.
Surely, I must be overlooking something or thinking about this wrong.

Michael Galvin
Muskegon, MI
 
S

Steve Holden

Michael said:
To see an example of what I am trying to accomplish, look at this page
on my personal website:

http://mysite.verizon.net/michaelgalvin/jan06call.html

I now realize my attachement could not be posted on this usenet group.
I suspect your best option would be to use ReportLab's open source
package (www.reportlab.org) to generate PDF files.

You may, however, be able to get at the Windows device context through
wxPython (www.wxpython.org): if you download the demonstration you'll
see that on Windows they do send fairly arbitrary graphics to the
Windows printer queue.

regards
Steve
 
M

Manlio Perillo

Michael Galvin ha scritto:
I am trying to use Python to send to the printer a calender filled
with a mix of text and simple graphics. I want to draw on the printed
page something like a table with 6 rows and 7 columns to represent a
calendar. I want to place text precisely within those boxes on the
printed page. I am using Python 2.4 on Windows XP

I was in the past able to do this within Visual Basic using its
printer object. Visual Basic's printer object uses a coordinate
system to allow you to draw lines and to place text on the printed
page precisely. I have attached a file "jan06call.jpg" to this message
to illustrate what I am trying to do.

Does Python have a module which would help me do this?

You can try to use pycairo for graphics, using postscript as a backend.
Then print the postscript file (with Ghostscript).

Or you can use a more high level tool.



Regards Manlio Perillo
 
R

Roger Upole

Pywin32 wraps most of the GDI functions used to draw
lines and text directly on a printer device context.
Many of them are only implemented as methods of
MFC objects rather than exposed directly.

See \win32\Demos\print_desktop.py for some examples
of working directly with a printer DC.

hth
Roger
 
P

Paul Boddie

Steve said:
I suspect your best option would be to use ReportLab's open source
package (www.reportlab.org) to generate PDF files.

One alternative, although I'm not convinced that it is actively
maintained any more, is the Piddle/Sping library [1]. As mentioned
elsewhere, the Cairo bindings would provide a similar developer
experience to that, and Cairo is increasingly fashionable.
You may, however, be able to get at the Windows device context through
wxPython (www.wxpython.org): if you download the demonstration you'll
see that on Windows they do send fairly arbitrary graphics to the
Windows printer queue.

PyQt [2] seems to support printing fairly conveniently. Consider this
very simple example:

from qt import *
import sys
qapp = QApplication(sys.argv)
printer = QPrinter(QPrinter.PrinterResolution)
printer.setPageSize(printer.A4)
printer.setOutputToFile(1)
printer.setOutputFileName("qtprint.ps")
painter = QPainter(printer)
painter.drawText(painter.window(), painter.AlignCenter, "Hello")
painter.end()

I haven't used printing in Qt [3] before, so apologies must go out if
I've made fundamental mistakes in the above code which did, admittedly,
produce output that resembled my expectations. Another route might be
to use a Tkinter canvas - at least in times of old, such canvases were
able to dump their contents as PostScript.

Paul

[1] http://piddle.sourceforge.net/
[2] http://www.riverbankcomputing.co.uk/pyqt/index.php
[3] http://doc.trolltech.com/3.3/graphics.html
 
K

Kevin

One option is to create your page as an image file using PIL (which can
handle your text and drawing requirements, as well as any
pictures/graphics), then print it to a windows printer using my
ImagePrintWin module.

ImagePrintWin can print to any normal windows printer, and includes an
optional GUI for doing a "Printer Setup" type dialog (including preview).
It can even handle ICC profiles for your printer if you want color accuracy.

You can download ImagePrintWin (GPL'd) from my site at:

http://www.cazabon.com/python/downloads/ImagePrintWin.py


The pyCMS module for doing ICC is available also on my site at:

http://www.cazabon.com/pyCMS/

Kevin Cazabon.
 
E

eric.howland

Michael said:
I am trying to use Python to send to the printer a calender filled
with a mix of text and simple graphics. I want to draw on the printed
page something like a table with 6 rows and 7 columns to represent a
calendar. I want to place text precisely within those boxes on the
printed page. I am using Python 2.4 on Windows XP

I was in the past able to do this within Visual Basic using its
printer object. Visual Basic's printer object uses a coordinate
system to allow you to draw lines and to place text on the printed
page precisely. I have attached a file "jan06call.jpg" to this message
to illustrate what I am trying to do.

Does Python have a module which would help me do this?

To put it another way, can Python control the placement of text and
graphics precisely on the printed page?

I have scoured my Python programming texts, python.org, and this
usenet group without success. Mark Lutz's wonderful book "Programming
Python" has not one reference to the word "printer" in its index.
Surely, I must be overlooking something or thinking about this wrong.

Michael Galvin
Muskegon, MI

This does something like you want using piddle. It is designed to make
a pdf of a calendar on a sheet of paper that has times blocked out (the
add_data and print_action methods).

import sys, os, string, re, calendar, time, datetime, copy
from optparse import OptionParser
from piddlePDF import *

class output_pdf:

setup = { #constants to use for spacing
"upperleftx": 0.75*72,
"upperlefty": 1*72,
"rowoffset": 2.0 * 72,
"coloffset": 1.0 * 72,
"vert_margin": 25,
"horz_margin": 25,
}

canvas = PDFCanvas() # backend you want to test
def __init__(self, year, month, title ):
### global canvas
self.printcal( year, month, title)



def printcal(self, year, month, label):
""" prints the days, and times and outside boxes for each day.
sets up a dictionary with the x and y offset for each day.
"""
global calpos
calpos = {}

wkdaytxt = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat']
calendar.setfirstweekday(calendar.SUNDAY)

# use calendar to figure out days for dates (a list of lists)
month_cal= calendar.monthcalendar( year, month)
#figure out how many weeks and days
daywk1st, days= calendar.monthrange( year, month)

if len(month_cal) == 6: self.setup["rowoffset"] = 1.8*72

self.canvas.drawString(label,
10,
self.setup["upperlefty"]- 40,
Font(face="sansserif",size=16,bold=1),
color=green)


for row, wk in enumerate(month_cal):
topy = self.setup["upperlefty"]+ row*self.setup["rowoffset"]
self.canvas.drawString('00:00', 10, topy+4,
Font(face="sansserif",size=8,bold=1),
color=darkorange)
self.canvas.drawString('12:00', 10,
topy+4+(self.setup["rowoffset"]-self.setup["vert_margin"])*.5 ,
Font(face="sansserif",size=8,bold=1),
color=darkorange)
self.canvas.drawLine( self.setup["upperleftx"]-10,

topy+(self.setup["rowoffset"]-self.setup["vert_margin"])*.5,
self.setup["upperleftx"]+
7*self.setup["coloffset"],

topy+(self.setup["rowoffset"]-self.setup["vert_margin"])*.5,
color=darkorange, width=1 )
self.canvas.drawString('08:00', 10,
topy+4+(self.setup["rowoffset"]-self.setup["vert_margin"])*(8/24.0) ,
Font(face="sansserif",size=6,bold=1),
color=darkorange)
self.canvas.drawLine( self.setup["upperleftx"]-10,

topy+(self.setup["rowoffset"]-self.setup["vert_margin"])*(8/24.0),
self.setup["upperleftx"]+
7*self.setup["coloffset"],

topy+(self.setup["rowoffset"]-self.setup["vert_margin"])*(8/24.0),
color=darkorange, width=1 )
self.canvas.drawString('17:00', 10,
topy+4+(self.setup["rowoffset"]-self.setup["vert_margin"])*(17/24.0) ,
Font(face="sansserif",size=6,bold=1),
color=darkorange)
self.canvas.drawLine( self.setup["upperleftx"]-10,

topy+(self.setup["rowoffset"]-self.setup["vert_margin"])*(17/24.0),
self.setup["upperleftx"]+
7*self.setup["coloffset"],

topy+(self.setup["rowoffset"]-self.setup["vert_margin"])*(17/24.0),
color=darkorange, width=1 )
self.canvas.drawString('24:00', 10,
topy+4+(self.setup["rowoffset"]-self.setup["vert_margin"]) ,
Font(face="sansserif",size=8,bold=1),
color=darkorange)

for col, date in enumerate(wk):
topx = self.setup["upperleftx"]+
col*self.setup["coloffset"]
self.canvas.drawString(wkdaytxt[col],
topx,
self.setup["upperlefty"]*.7,
Font(face="sansserif",size=16,bold=1),
color=green)
topx = self.setup["upperleftx"]+
col*self.setup["coloffset"]
topy = self.setup["upperlefty"]+
row*self.setup["rowoffset"]
calpos[date] = (topx, topy)


for i in range(days):
topx, topy = calpos[i+1]

self.canvas.drawRect( topx, topy,

(topx+(self.setup["coloffset"]-self.setup["horz_margin"])),

(topy+(self.setup["rowoffset"]-self.setup["vert_margin"])),
edgeColor=black, edgeWidth=2,
fillColor=transparent)
self.canvas.drawString('%d'%(i+1), topx, topy-2 ,
Font(face="sansserif",size=12,bold=1),
color=red)



def date_str2value(self,intime):
tuple_names = ["tm_year", "tm_mon", "tm_mday", "tm_hour",
"tm_min", "tm_sec", "tm_wday", "tm_yday", "tm_isdst"]
t_tuple = time.localtime(intime)
t_dict = {}
for i, name in enumerate(tuple_names):
t_dict[name] = t_tuple
floattime = (float(t_dict['tm_hour'])*60 +
float(t_dict['tm_min']))/float(24*60)

return t_dict, floattime

def print_action(self,year,month, action):
##action_list = re.split(r'\t', action)
##starttime = action_list[1]
##endtime = action_list[2]
client = action['destination']

s_dict, s_time = self.date_str2value(action['start_sec'])
e_dict, e_time = self.date_str2value(action['stop_sec'])
##print s_dict, s_time, ":-:", e_dict, e_time
if (s_dict['tm_mday'] == e_dict['tm_mday'] and
s_dict['tm_mon'] == int(month) and
s_dict['tm_year'] == int(year)):
topx, topy = calpos[s_dict['tm_mday']]
ypos_start = topy + (s_time *
(self.setup["rowoffset"]-self.setup["vert_margin"]))
ypos_end = topy + (e_time *
(self.setup["rowoffset"]-self.setup["vert_margin"]))
right_side = topx +
(self.setup["coloffset"]-self.setup["horz_margin"])

self.canvas.drawRect( topx, ypos_start,
right_side, ypos_end,
edgeColor=black, edgeWidth=1,
fillColor=skyblue)
self.canvas.drawString(client, topx+2, ypos_start+5,
Font(face="sansserif",size=5,bold=0),
color=darkorchid)

def add_data(self, year, month, data):
for action in data:
#print "adding data", action
self.print_action(year, month, action)

def save(self, filename):
self.canvas.flush()
self.canvas.save(filename)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top