I made this Python program that uses psutil and turtle to graph a computer's CPU usage, real time. My problem is, when the turtle hits the edge of the window it keeps going, out of view - but I want to make the window scroll right, so the turtle continues graphing the CPU usage while staying at the edge of the window. How can I get the turtle to stay in view?
import turtle
import psutil
import time
# HOW TO MAKE THE DOTS THAT WHEN YOU HOVER OVER THEM IT SHOWS THE PERCENT
# HOW TO MAKE IT CONTINUE SCROLLING ONCE THE LINE HITS THE END
# Set up the turtle
screen = turtle.Screen()
screen.setup(width=500, height=125)
# Set the width to the actual width, -20% for a buffer
width = screen.window_width()-(screen.window_width()/20)
# Set the height to the actual height, -10% for a buffer
height = screen.window_height()-(screen.window_height()/10)
# Create a turtle
t = turtle.Turtle()
t.hideturtle()
t.speed(0)
t.penup()
# Set x_pos to the width of the window/2 (on the left edge of the window)
x_pos = -(width/2)
# Set y_pos to the height of the window/2 (on the bottom of the window)
y_pos = -(height/2)
# Goto the bottom left corner
t.goto(x_pos, y_pos)
t.pendown()
while True:
# Get the CPU %
cpu_percent = psutil.cpu_percent(interval=None)
#Make the title of the Turtle screen the CPU %
screen.title(f"CPU %: {cpu_percent}%")
#Set y_pos as the bottom of the screen, +1% of the height of the screen for each CPU %
y_pos = (-height/2)+((height/100)*cpu_percent)
# Goto the point corresponding with the CPU %
t.goto(x_pos, y_pos)
# Make a dot
t.dot(4, "Red")
# Make add 5 to x_pos, so the next time it is farther to the left
x_pos = x_pos+5
You can apply a Flappy Bird design to this problem. In that game, it looks like the bird is flying forward, but the implementation is actually such that the pipes are moving from the right side of the screen to the left and the bird doesn't move at all on the x-axis.
Applying this to your case, you can slowly move the dots in the graph to the left and keep the turtle at the same spot once it gets close to the right.
The easiest way to implement this is with a queue data structure. The oldest CPU reading (or pipe) that falls off the left side of the screen is pruned (dequeued) and a new reading (or pipe) is added (enqueued) to the right side of the screen.
Now, to achieve the illusion of movement, you can clear and redraw the whole screen on every frame. Achieving this in turtle involves disabling the internal update loop with tracer(0)
, then calling update()
to draw a frame. You can use clear()
to clear the drawings from the last frame (reset()
is sometimes handy too).
Finally, the while True:
approach is a poor event loop that just tries to run as fast as possible with no regard for framerate. Use ontimer
for a somewhat more consistent framerate.
Here's a proof of concept.
import psutil # 5.9.5
import turtle
from collections import deque
def tick():
cpu_percent = psutil.cpu_percent(interval=None)
screen.title(f"CPU %: {cpu_percent}%")
y_pos = -height / 2 + height / 100 * cpu_percent
positions.append(y_pos)
if len(positions) > width / step:
positions.popleft()
t.penup()
t.clear()
for i, y_pos in enumerate(positions):
x_pos = width / -2 + i * step
t.goto(x_pos, y_pos)
t.pendown()
t.dot(4, "red")
turtle.update()
screen.ontimer(tick, rough_fps)
step = 5
rough_fps = 1000 // 30
turtle.tracer(0)
screen = turtle.Screen()
screen.setup(width=500, height=500)
width = screen.window_width()
height = screen.window_height()
t = turtle.Turtle()
t.hideturtle()
positions = deque()
screen.ontimer(tick, rough_fps)
turtle.exitonclick()