7

For duplicate-markers: I am fully aware that there are some similar questions in matplotlib, such as this one. My question is about Tkinter not matplotlib.

I am now importing Lena into python and drawing a green dot at her hat with

In [72]: from PIL import Image
   ....: import matplotlib.pylab as plt
   ....: im = Image.open('lena.jpg')
   ....: fig = plt.figure()
   ....: axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])
   ....: axes.imshow(im)
   ....: axes.scatter(50, 50, marker='s', color='green')
Out[72]: <matplotlib.collections.PathCollection at 0xb3e2ef0>

(Please ignore the red dot)

enter image description here

I now want the green dot (50, 50) to be still on Lena's hat, but I also want the green dot to be drawn at the left bottom corner instead of the left top corner.

I expect something like this:

enter image description here

As seen, I managed to do this easily in matplotlib with one additional line:

axes.invert_yaxis()

Question

I am now drawing on the canvas in Tkinter. How may I achieve the same effect?


Update

Lena is merely for illustration of my purpose. In my real problem, I am not importing anything in Tkinter. I merely draw on a empty canvas. I am reluctant to modify my data, I only wish to have the drawing upside down. Like in my Lena illustration, the coordinate is still (50, 50). The difference is that now it is in the left bottom instead of top corner.

Community
  • 1
  • 1
  • Could you show your Tkinter code? – falsetru Oct 27 '13 at 06:00
  • @falsetru My code is quite a mess. But I think I've made it clear, though I only use the description. You can think my code as one drawing dots on the canvas, which is extremely simple. Now I wish my left bottom corner to be (0, 0) –  Oct 27 '13 at 06:10

3 Answers3

2

An angle can be used like such:

image = Image.open("lena.jpg")
angle = 180
tkimage = ImageTk.PhotoImage(image.rotate(angle))
...

It would be possible to draw the picture, and use reversed coordinates (so when you know the size of the canvas, instead of saying 50x50, you could use (max-50)x(max-50).

The question is whether axes.imshow can handle the ImageTk.PhotoImage. Then again, I am not entirely sure if you'd just want this on a Tkinter canvas instead, e.g.:

canvas_obj = self.canvas.create_image(250, 250, image=tkimage)
PascalVKooten
  • 20,643
  • 17
  • 103
  • 160
  • Oh, Lena is merely for illustration of my purpose. In my real problem, I am not importing anything in Tkinter. I merely draw on a empty canvas. I am reluctant to modify my data, I only wish to have the drawing upside down. –  Oct 27 '13 at 13:14
  • @mavErick So the question is to reverse the canvas? Or would drawing inversely be okay as well (then you draw everything using `(max-50)` for the inverse of 50)? – PascalVKooten Oct 27 '13 at 13:39
  • I think drawing reversely will do, but as I said I am really reluctant to modify my data points specially for drawing. –  Oct 27 '13 at 14:43
  • What do you draw? What is the purpose? could you save the points first to a file which you would then reload and reverse? I don't think it is possible to rotate the canvas in the way you describe. – PascalVKooten Oct 27 '13 at 14:59
1

It seems to me that this would be simple with code like the below:

import Tkinter
#Set up a basic canvas
top = Tkinter.Tk()
canv = Tkinter.Canvas(top, bg="brown", height=250, width=300)

#Replace with what ever values you want
x = 50
y = 50

#Draw the first dot
line1 = canv.create_line(x, y, x - 2, y - 2, fill="green", width=3)
#This next line is pretty much all it takes to find the Y inverse
y = canv.winfo_reqheight() - y
#Draw the second dot
line2 = canv.create_line(x, y, x - 2, y - 2, fill="green", width = 3)

canv.pack()
top.mainloop()

This returns the following:

Flipped Y axis

Basically all I did was get the canvas height (250), and subtract the previous Y value (50) from it, which returned the Y inverse (200). Not exactly a built in function, but the actual flipping part was very simple. Hope that was what you were looking for... Good luck!

Community
  • 1
  • 1
SuperPrograman
  • 1,814
  • 17
  • 24
0

What you seem to be asking for is a 2D World to Viewport Transformation:

Take an area defined in "world coordinates" (say 10 metres by 10 metres) and map it to an area defined in canvas coordinates.

eg.

from tkinter import *

xmin,ymin,xmax,ymax = 0,0,10,10   # world
umin,vmin,umax,vmax = 0,480,640,0 # viewport (note: y reversed)

points = [(2,2), (4,4), (7,7), (8,8)]  # some "world" points

def world_to_viewport(worldpoint):
    x,y = worldpoint
    u = (x - xmin)*((umax - umin)/(xmax - xmin)) + umin
    v = (y - ymin)*((vmax - vmin)/(ymax - ymin)) + vmin
    return u,v

def pixel_to_world(pixel):
    u,v = pixel
    x = (u - umin)*((xmax - xmin)/(umax - umin)) + xmin
    y = (v - vmin)*((ymax - ymin)/(vmax - vmin)) + ymin
    return x,y

root = Tk()
canvas = Canvas(root, width=640, height=480, bd=0, highlightthickness=0)
canvas.pack()

def on_click(event):
    root.title('%s,%s' %(pixel_to_world((event.x,event.y))))

canvas.bind('<ButtonPress-1>', on_click)

r = 5
for point in points:
    cx,cy = world_to_viewport(point)
    canvas.create_oval(cx-r,cy-r,cx+r,cy+r,fill='red')

root.mainloop()
Oblivion
  • 1,669
  • 14
  • 14