4

I am using Tkinter to visualize my data points. My problem is that I cannot make the data points appear in the center of the canvas and meanwhile the canvas is big enough.

To make the canvas look good, I wish to fix it at around 800*600 (I think the unit is pixel). So I did the following:

class DisplayParticles(Canvas):
    def __init__(self):
        # Canvas
        Canvas.__init__(self)
        self.configure(width=800, height=600)
        # Particles
        self.particle_radius = 1
        self.particle_color = 'red'
        # User
        self.user_radius = 4
        self.user_color = 'blue'
        self.ghost_color = None

However, my data to be plotted are in the unit of meter. Plus, they center around the origin (0, 0), which means that there are negative coordinates for both x and y.

Then when I plot them on the canvas I get something like this

enter image description here

Obviously, the data points were plotted in pixel!

I wish the canvas to be big enough on the screen and meanwhile the data are plotted in a proper scale centered at the canvas. (Place my origin (0, 0) at the canvas center)

How may I do that?

3 Answers 3

6

The visible center of the canvas can be changed by setting the scrollregion attribute. For example, if you set the scrollregion to (-400,-400, 400, 400) in a canvas that is 800 pixels wide, the coordinate 0,0 will appear in the center of the screen.

Here's an example that draws a square at 0,0, and which appears in the center of the screen:

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self,*args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)

        self.canvas = tk.Canvas(width=800, height=800)
        self.canvas.pack(side="top", fill="both", expand=True)
        self.canvas.configure(scrollregion=(-400, -400, 400, 400))

        self.canvas.create_rectangle(-10,-10,10,10, fill="red", outline="black")

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

You can also use the xview_scroll and yview_scroll methods to move 0,0 into the center of the visible portion of the canvas. Instead of setting the scrollregion as in the above example, you can do this after creating your canvas:

self.canvas.xview_scroll(800, "units")
self.canvas.yview_scroll(800, "units")

This will programmatically scroll the canvas over and down 800 pixels, so that 0,0 is in the center of the screen.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I successfully place the origin in the center. But as seen in my question, I also hope to define my window size with data unit (m) instead of pixels. This way I can make my dots look bigger. What I have now is like this: imgur.com/xqANQ1L
0

Use the xview and yview methods to scroll the canvas view so the origin is in the center.

Scaling is not supported, so if you need that, you need to transform the source data, like Brionius suggests.

Comments

-1

Your Canvas is not going to automatically scale to fit what you've drawn - you'll have to figure out what the proper size is and set it.

Also, Canvas coordinates will always start with (0, 0) in the upper left corner - no way to change that. That means you'll have to translate all the points you plot on the canvas. Luckily, that's easy:

width = ...   # Determine the correct width
height = ...  # Determine the correct height
self.configure(width=width, height=height)

coords = (-20, -30, 10, 60)  # The coordinates of a shape you want to draw

# add width/2 and height/2 to x and y coordinates respectively so that the (0, 0) coordinate is shifted to the center of the canvas:
newCoords = (coords[0]+width/2, coords[1]+height/2, coords[2]+width/2, coords[3]+height/2)  

self.create_oval(*newCoords)  # Create the translated shape

1 Comment

What you say is not true -- you can move 0,0 away from the upper-left corner by changing the scrollregion attribute, or by calling the xview and yview methods. There is no need to do math on the coordinates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.