Reputation: 386
As a practice I am generating bars using the turtle module in python.
Using the following code and achieved a simple bar graph but there is a detail that I would like to improve.
import turtle
def generaVentana():
w = turtle.Screen()
w.title("Ejercicio 7, 8")
w.bgcolor("lightgreen")
return w
def generaTortuga():
t = turtle.Turtle()
t.pensize(2)
return t
wn = generaVentana()
tess = generaTortuga()
xs = [48, 117, -200, 240, 160, 260, 220]
def draw_bar(t, height):
if (height < 100):
t.color("black", "green")
elif (height >= 100 and height < 200):
t.color("black", "yellow")
elif (height >= 200):
t.color("black", "red")
t.begin_fill()
t.left(90)
t.forward(height)
t.right(90)
t.write(" " + str(height))
t.forward(40)
t.right(90)
t.forward(height)
t.left(90)
t.end_fill()
t.penup()
t.forward(10)
t.pendown()
for v in xs:
draw_bar(tess, v)
wn.mainloop()
When defining a bar with negative value it is generated but the size of the bar that is printed with the write () function I see that it is displayed on the inside of the bar.
But I want it to be displayed on the outside of the bar.
And tried to use in the code the line break tag "\n" concatenated with the value of the height returned string but it does not work.
There is some way to force this behavior, Thank you.
Upvotes: 2
Views: 2234
Reputation: 41905
I would take control of your font size so you can move relative to the current font rather than estimating for the default font:
from turtle import Screen, Turtle
xs = [48, 117, -200, 240, 160, 260, 220]
FONT_SIZE = 12
FONT = ('Arial', FONT_SIZE, 'normal')
def generaVentana():
screen = Screen()
screen.title("Ejercicio 7, 8")
screen.bgcolor("lightgreen")
return screen
def generaTortuga():
turtle = Turtle()
turtle.pensize(2)
turtle.penup()
return turtle
def draw_bar(t, height):
if height < 100:
t.fillcolor("green")
elif 100 <= height < 200:
t.fillcolor("yellow")
else:
t.fillcolor("red")
t.left(90)
t.pendown()
t.begin_fill()
t.forward(height)
t.right(90)
t.forward(20)
if height < 0:
t.penup()
position = t.position() # save
t.sety(t.ycor() - FONT_SIZE - t.pensize())
t.write(height, align='center', font=FONT)
if height < 0:
t.setposition(position) # restore
t.pendown()
t.forward(20)
t.right(90)
t.forward(height)
t.end_fill()
t.penup()
t.left(90)
t.forward(10)
wn = generaVentana()
tess = generaTortuga()
for value in xs:
draw_bar(tess, value)
wn.mainloop()
Upvotes: 1
Reputation: 350841
The logic is that the text is written with the current turtle position as baseline, and so text always appears above that position.
When you are on the negative side, you would need to move some extra distance downward before writing the text. This is a bit cumbersome to do in the middle of a bar drawing operation, so I would separate the label printing from the bar drawing, like this:
def draw_bar(t, height):
if height < 100:
t.color("black", "green")
elif height >= 100 and height < 200:
t.color("black", "yellow")
else: # no need to put a condition here
t.color("black", "red")
# add this block:
t.left(90)
p = t.position()
t.penup()
# when height is negative, move 14 more in that downward direction.
t.forward(height - 14 * int(height < 0))
t.write(" " + str(height))
t.goto(p)
t.pendown()
# end of added block
t.begin_fill()
# removed: t.left(90)
t.forward(height)
t.right(90)
# removed: t.write(" " + str(height))
t.forward(40)
t.right(90)
t.forward(height)
t.left(90)
t.end_fill()
t.penup()
t.forward(10)
t.pendown()
BTW: the final elif
is not needed, you can just do else
. Also, you don't need parentheses around if
conditions.
You might also want to consider centering the printed text to the center of the bar. Change this line:
t.write(" " + str(height))
to:
t.right(90)
t.forward(20) # move to (horizontal) center of bar
t.write(str(height), align="center")
t.left(90)
Upvotes: 1