I am using python turtle library to draw a big diagram. Whenever it's drawn the displayed region is the center (i.e. the scrollbar's are in the middle position). I'd like to scroll to the top-left region. Is there any way to do that?
Found solution:
ts = getscreen().getcanvas()
ts.xview_moveto(0)
ts.yview_moveto(0)
You can also make the screen bigger and you can manually scroll it.
screen = turtle.Screen()
screen.screensize(x ,y)
Just make the x bigger and you can scroll manually (by default the x is 400 and the y is 300)
Related
This maybe a very stupid question but I am having some troubles with tkinter. I am very new to using tkinter and wanted to learn something during my free time which I don't have much of. I have set up the canvas and everything but in a pickle when I try to dare a rectangle with negative points. I don't kow why, it just doesn't draw anything.
What I am trying to do is to draw a rectangle underneath one another.
I have attached the code below. It draws the rectangle which is filled with green, but when I try to draw the rectangle filled with red, nothing appears.
I really appreciate the help.
from tkinter import *
mainWindow = Tk()
drawingCanvas = Canvas(mainWindow, width=300, height=300)
drawingCanvas.pack()
drawingCanvas.create_rectangle(50, 25, 150, 75, fill="green")
drawingCanvas.create_rectangle(50, -200, 150, -100, fill="red")
mainloop()
I tried to plot the points using using a online plotter demos to check if the points are correct. It is, but whne I draw it in tkinter, the rectangle with negative points is missing/doesn't get drawn.
The top-left corner of the canvas defaults to 0,0. Since your objects are being drawn above that coordinate they aren't visible.
You can adjust the scrollregion after you've created the objects, and the canvas will be adjusted so that the top-left-most object is visible. You can do this with the following statement, which should come after you've created the items on the canvas:
drawingCanvas.configure(scrollregion=drawingCanvas.bbox("all"))
drawingCanvas.bbox("all") returns the bounding box of all of the items on the canvas. This is then passed into the configure method to change the scrollregion attribute of the canvas.
This works in this specific case since everything you draw will fit on the window. If you draw items far to the right or far below they won't be visible. This is a convenient way to adjust the viewable portion of the canvas which, as a side effect, adjusts what is displayed in the upper-left corner.
The rectangle with negative points is not missing but is drown outside of the screen. A tkinter Canvas starts at 0/0 on the top left of the screen so negative numbers will be drawn outside the window.
Change:
drawingCanvas.create_rectangle(50, -200, 150, -100, fill="red")
To:
drawingCanvas.create_rectangle(50, 200, 150, 100, fill="red")
Tkinter has this method:
window_name.attributes('-fullscreen',True)
and customtkinter?
I haven't found anything but
geometry(f"{WIDTH}x{HEIGHT}")
However when I grab screen size and put as WIDTH & HEIGHT the screen does change the size but does not go full size, I mean it is always shifted to the right so the windows leaves the margin on the left and top and the part of the window goes out of the screen to the right.
I'm working on an image annotation tool using Tkinter. A rectangular bounding box is following the cursor and is placed on the image by clicking. Now I need to be able to resize the bounding box and I'd like to do it in a similar fashion as it's done in Photoshop, holding down a button and depending on where the mouse is moved, the brush changes in size. Is that possible in Tkinter?
I've come up with this, where I wanted to add the pointer distance traveled in each direction to the rectangles size:
self.canvas.bind('<Alt_L>', self.resize)
self.previousx = 0
self.previousy = 0
def resize(self, event):
x = self.canvas.canvasx(event.x) # get coordinates of the event on the canvas
y = self.canvas.canvasy(event.y)
self.rect_size[0] += (self.previousx - x) # width
self.rect_size[1] += (self.previousy - y) # height
self.motion(event)
self.previousx = self.canvas.canvasx(event.x)
self.previousy = self.canvas.canvasy(event.y)
It kind of works too but
the previous coordinates need to be initialized with a different key first which is very annoying and
when the cursor - and with it the rectangle too - changes position it is very hard to tell if the rectangle is already the proper size.
How can I keep the cursor at the same spot and still get the mouse movements?
Edit:
Bryan in the comments was right, you can't move the mouse without also moving the on-screen cursor, which is true at least for my purposes. The solution was very simple, while resizing the bounding box I stopped updating it's position, so while the mouse was still moving, the rectangle did not.
Bryan in the comments was right, you can't move the mouse without also moving the on-screen cursor, which is true at least for my purposes. The solution was very simple, while resizing the bounding box I stopped updating it's position, so while the mouse was still moving, the rectangle did not.
I am new to Python and have been working with the turtle module as a way of learning the language.
Thanks to stackoverflow, I researched and learned how to copy the image into an encapsulated postscript file and it works great. There is one problem, however. The turtle module allows background color which shows on the screen but does not show in the .eps file. All other colors, i.e. pen color and turtle color, make it through but not the background color.
As a matter of interest, I do not believe the import of Tkinter is necessary since I do not believe I am using any of the Tkinter module here. I included it as a part of trying to diagnose the problem. I had also used bgcolor=Orange rather than the s.bgcolor="orange".
No Joy.
I am including a simple code example:
# Python 2.7.3 on a Mac
import turtle
from Tkinter import *
s=turtle.Screen()
s.bgcolor("orange")
bob = turtle.Turtle()
bob.circle(250)
ts=bob.getscreen()
ts.getcanvas().postscript(file = "turtle.eps")
I tried to post the images of the screen and the .eps file but stackoverflow will not allow me to do so as a new user. Some sort of spam prevention. Simple enough to visualize though, screen has background color of orange and the eps file is white.
I would appreciate any ideas.
Postscript was designed for making marks on some medium like paper or film, not raster graphics. As such it doesn't have a background color per se that can be set to given color because that would normally be the color of the paper or unexposed film being used.
In order to simulate this you need to draw a rectangle the size of the canvas and fill it with the color you want as the background. I didn't see anything in the turtle module to query the canvas object returned by getcanvas() and the only alternative I can think of is to read the turtle.cfg file if there is one, or just hardcode the default 300x400 size. You might be able to look at the source and figure out where the dimensions of the current canvas are stored and access them directly.
Update:
I was just playing around in the Python console with the turtle module and discovered that what the canvas getcanvas() returns has a private attribute called _canvas which is a <Tkinter.Canvas instance>. This object has winfo_width() and winfo_height() methods which seem to contain the dimensions of the current turtle graphics window. So I would try drawing a filled rectangle of that size and see if that gives you what you want.
Update 2:
Here's code showing how to do what I suggested. Note: The background must be drawn before any other graphics are because otherwise the solid filled background rectangle created will cover up everything else on the screen.
Also, the added draw_background() function makes an effort to save and later restore the graphics state to what it was. This may not be necessary depending on your exact usage case.
import turtle
def draw_background(a_turtle):
""" Draw a background rectangle. """
ts = a_turtle.getscreen()
canvas = ts.getcanvas()
height = ts.getcanvas()._canvas.winfo_height()
width = ts.getcanvas()._canvas.winfo_width()
turtleheading = a_turtle.heading()
turtlespeed = a_turtle.speed()
penposn = a_turtle.position()
penstate = a_turtle.pen()
a_turtle.penup()
a_turtle.speed(0) # fastest
a_turtle.goto(-width/2-2, -height/2+3)
a_turtle.fillcolor(turtle.Screen().bgcolor())
a_turtle.begin_fill()
a_turtle.setheading(0)
a_turtle.forward(width)
a_turtle.setheading(90)
a_turtle.forward(height)
a_turtle.setheading(180)
a_turtle.forward(width)
a_turtle.setheading(270)
a_turtle.forward(height)
a_turtle.end_fill()
a_turtle.penup()
a_turtle.setposition(*penposn)
a_turtle.pen(penstate)
a_turtle.setheading(turtleheading)
a_turtle.speed(turtlespeed)
s = turtle.Screen()
s.bgcolor("orange")
bob = turtle.Turtle()
draw_background(bob)
ts = bob.getscreen()
canvas = ts.getcanvas()
bob.circle(250)
canvas.postscript(file="turtle.eps")
s.exitonclick() # optional
And here's the actual output produced (rendered onscreen via Photoshop):
I haven't found a way to get the canvas background colour on the generated (Encapsulated) PostScript file (I suspect it isn't possible). You can however fill your circle with a colour, and then use Canvas.postscript(colormode='color') as suggested by #mgilson:
import turtle
bob = turtle.Turtle()
bob.fillcolor('orange')
bob.begin_fill()
bob.circle(250)
bob.begin_fill()
ts = bob.getscreen()
ts.getcanvas().postscript(file='turtle.eps', colormode='color')
Improving #martineau's code after a decade
import turtle as t
Screen=t.Screen()
Canvas=Screen.getcanvas()
Width, Height = Canvas.winfo_width(), Canvas.winfo_height()
HalfWidth, HalfHeight = Width//2, Height//2
Background = t.Turtle()
Background.ht()
Background.speed(0)
def BackgroundColour(Colour:str="white"):
Background.clear() # Prevents accumulation of layers
Background.penup()
Background.goto(-HalfWidth,-HalfHeight)
Background.color(Colour)
Background.begin_fill()
Background.goto(HalfWidth,-HalfHeight)
Background.goto(HalfWidth,HalfHeight)
Background.goto(-HalfWidth,HalfHeight)
Background.goto(-HalfWidth,-HalfHeight)
Background.end_fill()
Background.penup()
Background.home()
BackgroundColour("orange")
Bob=t.Turtle()
Bob.circle(250)
Canvas.postscript(file="turtle.eps")
This depends on what a person is trying to accomplish but generally, having the option to select which turtle to use to draw your background to me is unnecessary and can overcomplicate things so what one can do instead is have one specific turtle (which I named Background) to just update the background when desired.
Plus, rather than directing the turtle object via magnitude and direction with setheading() and forward(), its cleaner (and maybe faster) to simply give the direct coordinates of where the turtle should go.
Also for any newcomers: Keeping all of the constants like Canvas, Width, and Height outside the BackgroundColour() function speeds up your code since your computer doesn't have to recalculate or refetch any values every time the function is called.
I am using ReportLab to make a pdf using Python. I want to add a shape to the canvas, and have that shape act as a hyperlink. What is the simplest way to make the rectangle in the following example link to google.com?
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
c = canvas.Canvas("hello.pdf")
# move the origin up and to the left, draw square
c.translate(inch,9*inch)
# How do I make this rectangle link to google.com?
c.rect(inch,inch,1*inch,1*inch, fill=1)
c.showPage()
c.save()
Call linkURL on the Canvas:
c.linkURL('http://google.com', (inch, inch, 2*inch, 2*inch), relative=1)
The rectangle is the clickable area, so you'd have to match that to the drawn rectangle. The arguments are two coordinates, twice x, y for the bottom-left and top-right corner.
See more examples in this blog post: http://www.hoboes.com/Mimsy/hacks/adding-links-to-pdf/
To complement the Martijn answer, the linkURL draw a rectangle using the "default" coordinate system, i.e., bottom+up/left+right. Since the default canvas use the top down coord, i suggest you to make a quick fix basing on your canvas height.