I'm using pyBarcode to generate PNGs and the number below the barcode is getting cut off on the right. How do I nudge it left a few pixels?
According to the documentation I need to do something like this:
barcode.writer.BaseWriter(paint_text=my_callback)
And define a callback like this:
my_callback(xpos, ypos)
and:
use self.text as text
How exactly do I apply all of that to my Django view (below)?
def barcode(request):
import barcode
from barcode.writer import ImageWriter
from cStringIO import StringIO
def mm2px(mm, dpi=300):
return (mm * dpi) / 25.4
class MyImageWriter(ImageWriter):
def calculate_size(self, modules_per_line, number_of_lines, dpi=300):
width = 2 * self.quiet_zone + modules_per_line * self.module_width
height = 1.0 + self.module_height * number_of_lines
if self.text:
height += (self.font_size + self.text_distance) / 3
return int(mm2px(width, dpi)), int(mm2px(height, dpi))
f = BarcodeForm(request.GET)
if f.is_valid():
try:
i = StringIO()
bc_factory = barcode.get_barcode_class(f.PYBARCODE_TYPE[f.cleaned_data['barcode_type']])
bc_factory.default_writer_options['quiet_zone'] = 1.0
bc_factory.default_writer_options['text_distance'] = 1.0
bc_factory.default_writer_options['module_height'] = 15.0
bc_factory.default_writer_options['module_width'] = 0.3
bc_factory.default_writer_options['font_size'] = 46
bc = bc_factory(f.cleaned_data['text'], writer=MyImageWriter())
bc.write(i)
return HttpResponse(i.getvalue(), mimetype='image/png')
except Exception, e:
return HttpResponseBadRequest(str(e))
else:
return HttpResponseBadRequest('Missing text or unsupported barcode type: %s' % f.errors)
Edit: After answering I noticed you've got a factory that's setting the quiet_zone to 1.0. Change that back to 6.5 and I'd imagine it will look fine.
Edit2: I misunderstood the exact problem you were experiencing.
For whatever reason the author of pyBarcode is putting the text centered in the middle of the bar code. When the render method calls _paint_text() it passes in xpos/2, which sets it in the middle of the barcode. I guess this is okay with the default font he's using, but when you increased the font, it no longer fits.
Instead I was able to place it on the left side, by overriding the _paint_text() method. In the last line below, the variable pos is just a tuple containing an (x,y) coordinate that tells PIL where to draw the text on the bar code. So I've made sure x is lined up with the bar code. If you need it right aligned, you could play around with the xpos variable to get it where you need.
Give this a shot:
class MyImageWriter(ImageWriter):
def calculate_size(self, modules_per_line, number_of_lines, dpi=300):
width = 2 * self.quiet_zone + modules_per_line * self.module_width
height = 1.0 + self.module_height * number_of_lines
if self.text:
height += (self.font_size + self.text_distance) / 3
return int(mm2px(width, dpi)), int(mm2px(height, dpi))
def _paint_text(self, xpos, ypos):
# this should align your font to the left side of the bar code:
xpos = self.quiet_zone
pos = (mm2px(xpos, self.dpi), mm2px(ypos, self.dpi))
font = ImageFont.truetype(FONT, self.font_size)
self._draw.text(pos, self.text, font=font, fill=self.foreground)
Related
So i'm trying to launch a Python script (originally available from here : https://github.com/dvdtho/python-photo-mosaic). Full code at the bottom of this post.
This basically creates a mosaic (from a source image), with the final image (mosaic) is composed of several other images (tiles).
My question is how I am supposed to fill the variables (the ones at line 212) in order to run the script (through Eclispe in my case).
Should I put directly something like this? (in my case the folder Desktop/tiles contains all the jpg files) :
tile_paths = glob.glob("C:/Users/Sylvia/Desktop/tiles/*.jpg") # I've added this line myself
def create_mosaic(source_path="C:\\Users\\Sylvia\\Desktop\\source\\1.jpg", target="C:\\Users\\Sylvia\\Desktop\\source\\result.jpg", tile_ratio=1920/800, tile_width=75, enlargement=8, reuse=True, color_mode='RGB', tile_paths=None, shuffle_first=30):
Last time i tried i got this error :
def create_mosaic(source, target, tile_ratio=1920/800, tile_width=75,
enlargement=8, reuse=True, color_mode='RGB', tile_paths,
shuffle_first=30):
^ SyntaxError: non-default argument follows default argument
I'm very lost, hopefully someone can help me.
Here's the code :
import time
import itertools
import random
import sys
import numpy as np
from PIL import Image
from skimage import img_as_float
from skimage.measure import compare_mse
def shuffle_first_items(lst, i):
if not i:
return lst
first_few = lst[:i]
remaining = lst[i:]
random.shuffle(first_few)
return first_few + remaining
def bound(low, high, value):
return max(low, min(high, value))
class ProgressCounter:
def __init__(self, total):
self.total = total
self.counter = 0
def update(self):
self.counter += 1
sys.stdout.write("Progress: %s%% %s" % (100 * self.counter / self.total, "\r"))
sys.stdout.flush()
def img_mse(im1, im2):
"""Calculates the root mean square error (RSME) between two images"""
try:
return compare_mse(img_as_float(im1), img_as_float(im2))
except ValueError:
print(f'RMS issue, Img1: {im1.size[0]} {im1.size[1]}, Img2: {im2.size[0]} {im2.size[1]}')
raise KeyboardInterrupt
def resize_box_aspect_crop_to_extent(img, target_aspect, centerpoint=None):
width = img.size[0]
height = img.size[1]
if not centerpoint:
centerpoint = (int(width / 2), int(height / 2))
requested_target_x = centerpoint[0]
requested_target_y = centerpoint[1]
aspect = width / float(height)
if aspect > target_aspect:
# Then crop the left and right edges:
new_width = int(target_aspect * height)
new_width_half = int(new_width/2)
target_x = bound(new_width_half, width-new_width_half, requested_target_x)
left = target_x - new_width_half
right = target_x + new_width_half
resize = (left, 0, right, height)
else:
# ... crop the top and bottom:
new_height = int(width / target_aspect)
new_height_half = int(new_height/2)
target_y = bound(new_height_half, height-new_height_half, requested_target_y)
top = target_y - new_height_half
bottom = target_y + new_height_half
resize = (0, top, width, bottom)
return resize
def aspect_crop_to_extent(img, target_aspect, centerpoint=None):
'''
Crop an image to the desired perspective at the maximum size available.
Centerpoint can be provided to focus the crop to one side or another -
eg just cut the left side off if interested in the right side.
target_aspect = width / float(height)
centerpoint = (width, height)
'''
resize = resize_box_aspect_crop_to_extent(img, target_aspect, centerpoint)
return img.crop(resize)
class Config:
def __init__(self, tile_ratio=1920/800, tile_width=50, enlargement=8, color_mode='RGB'):
self.tile_ratio = tile_ratio # 2.4
self.tile_width = tile_width # height/width of mosaic tiles in pixels
self.enlargement = enlargement # mosaic image will be this many times wider and taller than original
self.color_mode = color_mode # mosaic image will be this many times wider and taller than original
#property
def tile_height(self):
return int(self.tile_width / self.tile_ratio)
#property
def tile_size(self):
return self.tile_width, self.tile_height # PIL expects (width, height)
class TileBox:
"""
Container to import, process, hold, and compare all of the tiles
we have to make the mosaic with.
"""
def __init__(self, tile_paths, config):
self.config = config
self.tiles = list()
self.prepare_tiles_from_paths(tile_paths)
def __process_tile(self, tile_path):
with Image.open(tile_path) as i:
img = i.copy()
img = aspect_crop_to_extent(img, self.config.tile_ratio)
large_tile_img = img.resize(self.config.tile_size, Image.ANTIALIAS).convert(self.config.color_mode)
self.tiles.append(large_tile_img)
return True
def prepare_tiles_from_paths(self, tile_paths):
print('Reading tiles from provided list...')
progress = ProgressCounter(len(tile_paths))
for tile_path in tile_paths:
progress.update()
self.__process_tile(tile_path)
print('Processed tiles.')
return True
def best_tile_block_match(self, tile_block_original):
match_results = [img_mse(t, tile_block_original) for t in self.tiles]
best_fit_tile_index = np.argmin(match_results)
return best_fit_tile_index
def best_tile_from_block(self, tile_block_original, reuse=False):
if not self.tiles:
print('Ran out of images.')
raise KeyboardInterrupt
#start_time = time.time()
i = self.best_tile_block_match(tile_block_original)
#print("BLOCK MATCH took --- %s seconds ---" % (time.time() - start_time))
match = self.tiles[i].copy()
if not reuse:
del self.tiles[i]
return match
class SourceImage:
"""Processing original image - scaling and cropping as needed."""
def __init__(self, image_path, config):
print('Processing main image...')
self.image_path = image_path
self.config = config
with Image.open(self.image_path) as i:
img = i.copy()
w = img.size[0] * self.config.enlargement
h = img.size[1] * self.config.enlargement
large_img = img.resize((w, h), Image.ANTIALIAS)
w_diff = (w % self.config.tile_width)/2
h_diff = (h % self.config.tile_height)/2
# if necesary, crop the image slightly so we use a
# whole number of tiles horizontally and vertically
if w_diff or h_diff:
large_img = large_img.crop((w_diff, h_diff, w - w_diff, h - h_diff))
self.image = large_img.convert(self.config.color_mode)
print('Main image processed.')
class MosaicImage:
"""Holder for the mosaic"""
def __init__(self, original_img, target, config):
self.config = config
self.target = target
# Lets just start with original image, scaled up, instead of a blank one
self.image = original_img
# self.image = Image.new(original_img.mode, original_img.size)
self.x_tile_count = int(original_img.size[0] / self.config.tile_width)
self.y_tile_count = int(original_img.size[1] / self.config.tile_height)
self.total_tiles = self.x_tile_count * self.y_tile_count
print(f'Mosaic will be {self.x_tile_count:,} tiles wide and {self.y_tile_count:,} tiles high ({self.total_tiles:,} total).')
def add_tile(self, tile, coords):
"""Adds the provided image onto the mosiac at the provided coords."""
try:
self.image.paste(tile, coords)
except TypeError as e:
print('Maybe the tiles are not the right size. ' + str(e))
def save(self):
self.image.save(self.target)
def coords_from_middle(x_count, y_count, y_bias=1, shuffle_first=0, ):
'''
Lets start in the middle where we have more images.
And we dont get "lines" where the same-best images
get used at the start.
y_bias - if we are using non-square coords, we can
influence the order to be closer to the real middle.
If width is 2x height, y_bias should be 2.
shuffle_first - We can suffle the first X coords
so that we dont use all the same-best images
in the same spot - in the middle
from movies.mosaic_mem import coords_from_middle
x = 10
y = 10
coords_from_middle(x, y, y_bias=2, shuffle_first=0)
'''
x_mid = int(x_count/2)
y_mid = int(y_count/2)
coords = list(itertools.product(range(x_count), range(y_count)))
coords.sort(key=lambda c: abs(c[0]-x_mid)*y_bias + abs(c[1]-y_mid))
coords = shuffle_first_items(coords, shuffle_first)
return coords
def create_mosaic(source_path, target, tile_ratio=1920/800, tile_width=75, enlargement=8, reuse=True, color_mode='RGB', tile_paths=None, shuffle_first=30):
"""Forms an mosiac from an original image using the best
tiles provided. This reads, processes, and keeps in memory
a copy of the source image, and all the tiles while processing.
Arguments:
source_path -- filepath to the source image for the mosiac
target -- filepath to save the mosiac
tile_ratio -- height/width of mosaic tiles in pixels
tile_width -- width of mosaic tiles in pixels
enlargement -- mosaic image will be this many times wider and taller than the original
reuse -- Should we reuse tiles in the mosaic, or just use each tile once?
color_mode -- L for greyscale or RGB for color
tile_paths -- List of filepaths to your tiles
shuffle_first -- Mosiac will be filled out starting in the center for best effect. Also,
we will shuffle the order of assessment so that all of our best images aren't
necessarily in one spot.
"""
config = Config(
tile_ratio = tile_ratio, # height/width of mosaic tiles in pixels
tile_width = tile_width, # height/width of mosaic tiles in pixels
enlargement = enlargement, # the mosaic image will be this many times wider and taller than the original
color_mode = color_mode, # L for greyscale or RGB for color
)
# Pull in and Process Original Image
print('Setting Up Target image')
source_image = SourceImage(source_path, config)
# Setup Mosaic
mosaic = MosaicImage(source_image.image, target, config)
# Assest Tiles, and save if needed, returns directories where the small and large pictures are stored
print('Assessing Tiles')
tile_box = TileBox(tile_paths, config)
try:
progress = ProgressCounter(mosaic.total_tiles)
for x, y in coords_from_middle(mosaic.x_tile_count, mosaic.y_tile_count, y_bias=config.tile_ratio, shuffle_first=shuffle_first):
progress.update()
# Make a box for this sector
box_crop = (x * config.tile_width, y * config.tile_height, (x + 1) * config.tile_width, (y + 1) * config.tile_height)
# Get Original Image Data for this Sector
comparison_block = source_image.image.crop(box_crop)
# Get Best Image name that matches the Orig Sector image
tile_match = tile_box.best_tile_from_block(comparison_block, reuse=reuse)
# Add Best Match to Mosaic
mosaic.add_tile(tile_match, box_crop)
# Saving Every Sector
mosaic.save()
except KeyboardInterrupt:
print('\nStopping, saving partial image...')
finally:
mosaic.save()
It's ok, this is the new file i have to create in order for it to work :
create_mosaic(
subject="/path/to/source/image",
target="/path/to/output/image",
tile_paths=["/path/to/tile_1" , ... "/path/to/tile_n"],
tile_ratio=1920/800, # Crop tiles to be height/width ratio
tile_width=300, # Tile will be scaled
enlargement=20, # Mosiac will be this times larger than original
reuse=False, # Should tiles be used multiple times?
color_mode='L', # RGB (color) L (greyscale)
)
Problem resovled.
I am doing a report in python reportlab. And I want to align some text from the right side. But each line of text has a different length, and I have to set coordinates manually. How can I do it dynamically?
pdf.setFont('Helvetica', 9)
pdf.drawString(400,600,"Rechnungsdatum: "+today)
pdf.drawString(390,590,"Leistungserbringung: "+master_data.loc[master_data['company']==company]['Leistungserbringung'][0]) #cus_specific
pdf.drawString(343,580,"Leistungszeitraum: "+start+" - "+end)
pdf.drawString(372,570,"Rechnungsnummer: "+master_data.loc[master_data['company']==company]['Rechnungsnummer'][0]) #cus_specific
pdf.drawString(398,560,"Lieferantennummer: "+master_data.loc[master_data['company']==company]['Lieferantennummer'][0]) #cus_specific
pdf.drawString(432,550,"Zahlungsziel: " +str((date.today().replace(day=1) - timedelta(days=1)).day)+ " Tage")
That's how it looks like:
[]
I want all lines to be aligned from the right side for a beautiful view. I am using Canvas and drawing each string via drawString(). Any help will be appreciated)
You can get canvas width using Canvas._pagesize[0], Canvas object has drawRightString method for right-aligning lines.
from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.units import inch, mm, cm, pica
from datetime import date, timedelta
if __name__ == "__main__":
pdf = Canvas("output.pdf")
pdf.setFont('Helvetica', 9)
master_data = ...
start = ...
end = ...
company = ...
today = ...
lines = [
"Rechnungsdatum: "+today,
"Leistungserbringung: "+master_data.loc[master_data['company']==company]['Leistungserbringung'][0],
"Leistungszeitraum: "+start+" - "+end,
"Rechnungsnummer: "+master_data.loc[master_data['company']==company]['Rechnungsnummer'][0],
"Lieferantennummer: "+master_data.loc[master_data['company']==company]['Lieferantennummer'][0],
"Zahlungsziel: " +str((date.today().replace(day=1) - timedelta(days=1)).day)+ " Tage",
]
ys = [600,590,580,570,560,550]
width = pdf._pagesize[0]
padding = 10 * mm
for y, line in zip(ys, lines):
pdf.drawRightString(width - padding, y, line)
pdf.save()
I have to create PDF file in which need to add lines at bottom left like footer.
Following code is working:
import StringIO
from reportlab.pdfgen import canvas
import uuid
def test(pdf_file_name="abc.pdf", pdf_size=(432, 648), font_details=("Times-Roman", 9)):
# create a new PDF with Reportla
text_to_add = "I am writing here.."
new_pdf = "test_%s.pdf"%(str(uuid.uuid4()))
packet = StringIO.StringIO()
packet.seek(0)
c = canvas.Canvas(pdf_file_name, pagesize = pdf_size)
#- Get the length of text in a PDF.
text_len = c.stringWidth(text_to_add, font_details[0], font_details[1])
#- take margin 20 and 20 in both axis
#- Adjust starting point on x axis according to text_len
x = pdf_size[0]-20 - text_len
y = 20
#- set font.
c.setFont(font_details[0], font_details[1])
#- write text,
c.drawString(x, y, text_to_add)
c.showPage()
c.save()
return pdf_file_name
Now if text have multiple lines then this is not working because length of text is greater than width of Page size. Understood.
I try with Frame and paragraph but still can not write text in correct position in a PDF
Following is code:
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Paragraph
styles = getSampleStyleSheet()
styleN = styles['Normal']
styleH = styles['Heading1']
def footer(canvas, doc):
canvas.saveState()
P = Paragraph("This is a multi-line footer. It goes on every page. " * 10, styleN)
w, h = P.wrap(doc.width, doc.bottomMargin)
print "w, h:", w, h
print "doc.leftMargin:", doc.leftMargin
P.drawOn(canvas, 10, 30)
canvas.restoreState()
def test():
doc = BaseDocTemplate('test.pdf', pagesize=(432, 648))
print "doc.leftMargin:", doc.leftMargin
print "doc.bottomMargin:", doc.bottomMargin
print "doc.width:", doc.width
print "doc.height:", doc.height
frame = Frame(10, 50, 432, 648, id='normal')
template = PageTemplate(id='test', frames=frame, onPage=footer)
doc.addPageTemplates([template])
text = []
for i in range(1):
text.append(Paragraph("", styleN))
doc.build(text)
Not understand why size of page change, because I set (432, 648) but is show (288.0, 504.0)
doc.leftMargin: 72.0
doc.bottomMargin: 72.0
doc.width: 288.0
doc.height: 504.0
Also Frame size:
w, h: 288.0 96
doc.leftMargin: 72.0
Do not know how to fix this issue.
I refer this link
First the mystery regarding the doc.width, the doc.width isn't the actual width of the document. It is the width of the area between the margins so in this case doc.width + doc.leftMargin + doc.rightMargin equals the width of the actual page.
Now back to why the footer did not span the entire width of the page as you wanted. This is because of the same issue as described above, namely doc.width isn't the actual paper width.
Assuming you want the footer to span the entire page
def footer(canvas, doc):
canvas.saveState()
P = Paragraph("This is a multi-line footer. It goes on every page. " * 10, styleN)
# Notice the letter[0] which is the width of the letter page size
w, h = P.wrap(letter[0] - 20, doc.bottomMargin)
P.drawOn(canvas, 10, 10)
canvas.restoreState()
Assuming you want the footer to span the width of the writable area
Note: the margins on the default setting are pretty big so that is why there is so much empty space on the sides.
def footer(canvas, doc):
canvas.saveState()
P = Paragraph("This is a multi-line footer. It goes on every page. " * 10, styleN)
w, h = P.wrap(doc.width, doc.bottomMargin)
print "w, h:", w, h
print "doc.leftMargin:", doc.leftMargin
P.drawOn(canvas, doc.leftMargin, 10)
canvas.restoreState()
EDIT:
As it might be useful to know where the normal text should start. We need to figure out the height of our footer. Under normal circumstances we cannot use P.height as it depends on the width of the text, calling it will raise a AttributeError.
In our case we actually are able to get the height of the footer either directly from P.wrap (the h) or by calling P.height after we have called P.wrap.
By starting our Frame at the height of the footer we will never have overlapping text. Yet it is important to remember to set the height of the Frame to doc.height - footer.height to ensure the text won't be placed outside the page.
I am fairly new to Processing but I have managed to make a good amount of a GUI in the Python Mode. I wanted to graph some data on a white box. I don't want to use background(0) because that'll make the entire window white. Using a rectangular in the draw() function also did not help as the rectangular kept on refreshing the graph. I am trying to simulate the hold on function as in MATLAB
Here's my pseudo code:
class plotEverything:
def __init__
def plotAxis
def plotGraph
def clearGraph
def setup():
size (800,600)
p1 = plotEverything()
background(0)
def draw():
rect (100,100,200,200)
fill(255)
p1.drawAxis()
p1.plotGraph()
Is there any way I can make that rectangle fixed in the background?
EDIT Added graph class | Ignore indents(Assume they are all properly indented) --
class graphData:
def __init__(self, originX, originY, xUpper, yUpper):
self.originX = originX
self.originY = originY
self.xUpper = xUpper
self.yUpper = yUpper
self.pointX1 = originX
self.pointX2 = xUpper
self.pointY1 = originY
self.pointY2 = yUpper
self.scaleFactorX = 10.0/(xUpper - originX) #Assuming data is between is 0 and 10
self.scaleFactorY = 10.0/(originY - yUpper) #Assuming data is between is 0 and 1
def drawAxis(self):
stroke(255)
strokeWeight(1.5)
line(self.originX, self.originY, self.originX, self.yUpper) #y axis
line(self.originX, self.originY, self.xUpper, self.originY) #x axis
def plotStaticData(self,data2Plot): #X-axis static
ab = zip(data2Plot,data2Plot[1:],data2Plot[2:],data2Plot[3:])[::2]
if ab:
(X1,Y1,X2,Y2) = ab[-1]
print (X1,Y1,X2,Y2)
self.pointX1 = self.originX + ceil((float(X1) - 0.0)/self.scaleFactorX)
self.pointX2 = self.originX + ceil((float(X2) - 0.0)/self.scaleFactorX)
self.pointY1 = self.originY - ceil((float(Y1) - 0.0)/self.scaleFactorY)
self.pointY2 = self.originY - ceil((float(Y2) - 0.0)/self.scaleFactorY)
stroke(255)
strokeWeight(2.0)
line(self.pointX1,self.pointY1,self.pointX2,self.pointY2)
def clearPlot(self):
background(0)
self.drawAxis()
I want to select features and to zoom on them and do all these steps using PyQgis.
And I'm able to do both of them separatly but it doesn't seems to work when I try to mix the two of them.
Both of the codes I use for them are from the internet. Here's what I use to select features of a layer :
from qgis.core import *
import qgis.utils
lyrMap = QgsVectorLayer('C:/someplace', 'MapName', 'ogr')
QgsMapLayerRegistry.instance().addMapLayer(lyrMap)
expr = QgsExpression("'Attribute' IS NOT NULL")
it = lyrMap.getFeatures(QgsFeatureRequest(expr))
ids = [i.id() for i in it] #select only the features for which the expression is true
lyrMap.setSelectedFeatures(ids)
And it seems to do the trick as features appear selected on QGis.
In order to zoom the code is much more simple, it's just :
canvas = qgis.utils.iface.mapCanvas()
canvas.zoomToSelected(lyrMap)
But it seems that canvas doesn't consider that there's a selection on lyrMap and simply do nothing. I've tried to do the selection manually in QGis, and then zoom using zoomToSelected, and it worked.
But my objective is to do it without needing to do the selection manually...
Note : I don't think that's the issue, but the attribute I'm doing the selection on is from a join between lyrMap and another layer (I didn't put the code here because I don't think it's linked).
Thanks in advances for answers, clues or anything really :) !
This is working for my plugin. I am using python 2.7 and QGIS 1.8 and 2.0.1.You can use this code after including using vector file and adding it to the registry.
self.rubberBand = None
#create vertex marker for point..older versons..
self.vMarker = None
#add rubberbands
self.crossRb = QgsRubberBand(iface.mapCanvas(),QGis.Line)
self.crossRb.setColor(Qt.black)
def pan(self):
print "pan button clicked!"
x = self.dlg.ui.mTxtX.text()
y = self.dlg.ui.mTxtY.text()
if not x:
return
if not y:
return
print x + "," + y
canvas = self.canvas
currExt = canvas.extent()
canvasCenter = currExt.center()
dx = float(x) - canvasCenter.x()
dy = float(y) - canvasCenter.y()
xMin = currExt.xMinimum() + dx
xMax = currExt.xMaximum() + dx
yMin = currExt.yMinimum() + dy
yMax = currExt.yMaximum() + dy
newRect = QgsRectangle(xMin,yMin,xMax,yMax)
canvas.setExtent(newRect)
pt = QgsPoint(float(x),float(y))
self.zoom(pt)
canvas.refresh()
def zoom(self,point):
canvas = self.canvas
currExt = canvas.extent()
leftPt = QgsPoint(currExt.xMinimum(),point.y())
rightPt = QgsPoint(currExt.xMaximum(),point.y())
topPt = QgsPoint(point.x(),currExt.yMaximum())
bottomPt = QgsPoint(point.x(),currExt.yMinimum())
horizLine = QgsGeometry.fromPolyline( [ leftPt , rightPt ] )
vertLine = QgsGeometry.fromPolyline( [ topPt , bottomPt ] )
self.crossRb.reset(QGis.Line)
self.crossRb.addGeometry(horizLine,None)
self.crossRb.addGeometry(vertLine,None)
if QGis.QGIS_VERSION_INT >= 10900:
rb = self.rubberBand
rb.reset(QGis.Point)
rb.addPoint(point)
else:
self.vMarker = QgsVertexMarker(self.canvas)
self.vMarker.setIconSize(10)
self.vMarker.setCenter(point)
self.vMarker.show()
# wait .5 seconds to simulate a flashing effect
QTimer.singleShot(500,self.resetRubberbands)
def resetRubberbands(self):
print "resetting rubberbands.."
canvas = self.canvas
if QGis.QGIS_VERSION_INT >= 10900:
self.rubberBand.reset()
else:
self.vMarker.hide()
canvas.scene().removeItem(self.vMarker)
self.crossRb.reset()
print "completed resetting.."