attempts to display the speedtest graph - python

Hello there i'm new to python and I'm trying to do speed testing using python getting data from (speedtest.net). I wrote the code, the speed shows, everything is fine, but now I need the graph to also be shown, as on the speedtest website itself. How to do it guys?
# Adding a library of window applications
from tkinter import *
# Adding a library of window applications
from speedtest import Speedtest
def test(): # Adding a function
download = Speedtest(secure=True).download()
upload = Speedtest(secure=True).upload()
download_speed = round(download / (10**6), 2)
upload_speed = round(upload / (10**6), 2)
download_label.config(text="Download Speed:\n" + str(download_speed) + "MbPs")
upload_label.config(text="upload_speed:\n" + str(upload_speed) + "MbPs")
root = Tk() # Adding a variable
root.title("speedTest") # Window name
root.geometry("300x400") # Window size
button = Button(root, text="Click to start", font=40, command=test) # Creating a button
button.pack(side=BOTTOM, pady=40) # Button display and location
download_label = Label(root, text="Download Speed:\n-", font=35) # Creating an icon
download_label.pack(pady=(50, 0))
upload_label = Label(root, text="upload_speed:\n-", font=35) # Creating an icon
upload_label.pack(pady=(10, 0))
root.mainloop() # Doesn't let you close the window until you close it yourself

Related

My goal is to run a Stepper through Python, but the values such as angular velocity and degrees are inputted by user through GUI

I'm having trouble with the Tkinter window not showing its contents and also storing the data inputted by the user into the stepper parameters. I got to run the Tkinter and the stepper in separate codes and it worked. But I'm not being able to integrate everything. Here's my code:
import time
from tkinter import *
from pymata4 import pymata4
top = Tk()
top.geometry("450x300")
pins = [8,9,10,11]
board = pymata4.Pymata4()
board.set_pin_mode_stepper(num_steps, pins)
num_steps = Label(top, text="Steps").place(x=40, y=60)
angular_velocity = Label(top, text="Angular Velocity").place(x=40,y=100)
submit_button = Button(top, text ="Submit").place(x=40,y=130)
num_steps_input_area = Entry(top, width=30).place(x=180,y=60)
angular_velocity_input_area = Entry(top, width=30).place(x=180, y=100)
angularvelocity = angular_velocity_input_area.get()
numsteps = num_steps_input_area.get()
while True:
board.stepper_write(angularvelocity, numsteps)
time.sleep(1)
board.stepper_write(angularvelocity, numsteps)
time.sleep(1)
top.mainloop()
I had to move quite a bit of things around. There may be some issues with this still as I am not familiar with all the context of the original code. However, hopefully it is good enough that you can see how to accomplish your goal.
I looked at the pymata4 module and there are some issues with what you are doing.
from tkinter import *
from pymata4 import pymata4
top = Tk()
top.geometry("450x300")
pins = [8,9,10,11]
board = pymata4.Pymata4()
# These variables need to be declared to be in the global space.
total_steps = 512 # Total number of steps per revolution of the stepper motor.
motorspeed = 0 # The library does not use angular velocity, but speed.
numsteps = 0 # To change direction use negative int, according to the module documentation.
complete = False # I added this to show how to stop running.
def actuate():
global motorspeed, numsteps, complete
board.stepper_write(motorspeed, numsteps)
if complete:
pass
else:
top.after(1000, actuate) # This will run actuate after 1000 ms
def set_input():
global pins, motorspeed, numsteps
motorspeed = motor_speed_var.get() # run .get() on IntVar object instead
numsteps = num_steps_var.get() # run .get() on IntVar object instead
board.set_pin_mode_stepper(total_steps, pins) # it was num_steps?
actuate()
num_steps = Label(top, text="Steps").place(x=40, y=60)
motor_speed = Label(top, text="Angular Velocity").place(x=40,y=100)
# Button requires a command definition or it is just for looks
submit_button = Button(top, text ="Submit" command=set_input).place(x=40,y=130)
num_steps_var = IntVar() # These are tkinter built in. There is also a StringVar
num_steps_input_area = Entry(top, width=30, textvariable=num_steps_var).place(x=180,y=60)
motor_speed_var = IntVar() # and a BooleanVar
motor_speed_input_area = Entry(top, width=30, textvariable=motor_speed_var).place(x=180, y=100)
top.mainloop()
Let me know if it works for you. I didn't run this.

Unable to hide Tkinter window while I am setting its geometry

I have a root window and I want to create a Toplevel window positioned in a specific place on the screen (centralized over the root window). So far I have been unable to accomplish this without seeing the Toplevel window quickly build itself in its default location and then hop over to the position I want it. I would prefer not to see this because it's weird and jarring.
Is there a way to build, then reposition a window in Tkinter without seeing it reposition itself?
Here's some example code with a sleep thrown in to simulate a complex window being rendered:
from tkinter import *
import time
def centralize_over_root(window_to_centralize):
root_geometry = root.winfo_geometry()
root_width_height = root_geometry.split('+')[0]
root_width = root_width_height.split('x')[0]
root_height = root_width_height.split('x')[1]
root_x_y = root_geometry.split(f'{root_height}+')[1]
root_x = root_x_y.split('+')[0]
root_y = root_x_y.split('+')[1]
window_to_centralize.update()
time.sleep(0.5)
window_width = window_to_centralize.winfo_width()
window_height = window_to_centralize.winfo_height()
window_x = int(root_x) + round((int(root_width) - int(window_width)) / 2.0)
window_y = int(root_y) + round((int(root_height) - int(window_height)) / 2.0)
result = f'+{window_x}+{window_y}'
return result
def new_window():
new_window = Toplevel(root)
Label(new_window, text='Something').pack(padx=20, pady=20)
new_window.geometry(centralize_over_root(new_window))
root = Tk()
Button(root, text='Make new window', command=new_window).pack(padx=50, pady=50)
root.mainloop()
You can hide the window using withdraw() and show it after reposition using deiconify():
def new_window():
new_window = Toplevel(root)
new_window.withdraw() # hide the window
Label(new_window, text='Something').pack(padx=20, pady=20)
new_window.geometry(centralize_over_root(new_window))
new_window.deiconify() # show the window
I think the following will do what you want. There are comments showing where I made changes. The problem was the time.sleep() was interfering with the mainloop() and your window_to_centralize.update() which makes it appear before you're finished configuring it.
from tkinter import *
import time
def centralize_over_root(window_to_centralize):
root_geometry = root.winfo_geometry()
root_width_height = root_geometry.split('+')[0]
root_width = root_width_height.split('x')[0]
root_height = root_width_height.split('x')[1]
root_x_y = root_geometry.split(f'{root_height}+')[1]
root_x = root_x_y.split('+')[0]
root_y = root_x_y.split('+')[1]
# window_to_centralize.update() # Don't do this - will happen automatically.
# time.sleep(0.5)
root.after(500) # This pauses without interfering with mainloop.
window_width = window_to_centralize.winfo_width()
window_height = window_to_centralize.winfo_height()
window_x = int(root_x) + round((int(root_width) - int(window_width)) / 2.0)
window_y = int(root_y) + round((int(root_height) - int(window_height)) / 2.0)
result = f'+{window_x}+{window_y}'
return result
def new_window():
new_window = Toplevel(root)
Label(new_window, text='Something').pack(padx=20, pady=20)
new_window.geometry(centralize_over_root(new_window))
root = Tk()
Button(root, text='Make new window', command=new_window).pack(padx=50, pady=50)
root.mainloop()

Loading GUI Python script on boot for raspberry pi

I'm on Raspberry Pi 3B+ (Raspbian) and I'm trying to load a Python script on boot which display 720p images into full screen mode, the user should then be able to press a push button to go to the next image.
Currently, I have created the code which allows for the images to display and the images to change due to the push button.
Right now I'm having trouble with having the images load into full screen mode and boot on start-up. I have followed many guides and tutorials on how I can load a GUI Python script on boot but none of them have seemed to work for my specific script (but they loaded on boot successfully from their example scripts) which is making me think that there's an issue in the code for why it won't boot (probably because I haven't implemented so that they open in full screen). These are all the guides which I tried out (https://www.raspberrypi-spy.co.uk/2015/02/how-to-autorun-a-python-script-on-raspberry-pi-boot/ , raspberry pi : Auto run GUI on boot , https://raspberrypi.stackexchange.com/questions/4123/running-a-python-script-at-startup , https://www.digikey.ca/en/maker/blogs/2018/how-to-run-python-programs-on-a-raspberry-pi , https://www.instructables.com/Raspberry-Pi-Launch-Python-script-on-startup/ , https://bc-robotics.com/tutorials/running-python-program-boot-raspberry-pi/) and I'd like to focus on the GUI method from this tutorial for my question (https://learn.sparkfun.com/tutorials/how-to-run-a-raspberry-pi-program-on-startup/all )
I'm very much a beginner right now when it comes to GUI programming (I took the original script from online and modified it to include the push button) and I'm not too sure on how I can implement the full screen option into the code which displays the images.
Here is what I have currently (will load images into a window, you can then change to the next image using a push button). At the beginning of my code, I tried adding in some functions from the example listed later which allowed toggling of full screen and also their associated root functions at the bottom to complement this
import tkinter as tk
from PIL import Image, ImageTk
import time
import sys
import os
import keyboard
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(10, GPIO.FALLING)
def toggle_fullscreen(event=None): # I added this in to try full screen
global root
global fullscreen
# Toggle between fullscreen and windowed modes
fullscreen = not fullscreen
root.attributes('-fullscreen', fullscreen)
resize()
# Return to windowed mode
def end_fullscreen(event=None): # I added this in to try full screen
global root
global fullscreen
# Turn off fullscreen mode
fullscreen = False
root.attributes('-fullscreen', False)
root= tk.Tk() # I added this in to try full screen
class HiddenRoot(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
#hackish way, essentially makes root window
#as small as possible but still "focused"
#enabling us to use the binding on <esc>
self.wm_geometry("0x0+0+0")
self.window = MySlideShow(self)
#self.window.changeImage()
self.window.startSlideShow()
class MySlideShow(tk.Toplevel):
def __init__(self, *args, **kwargs):
tk.Toplevel.__init__(self, *args, **kwargs)
#remove window decorations
self.overrideredirect(True)
#save reference to photo so that garbage collection
#does not clear image variable in show_image()
self.persistent_image = None
self.imageList = []
self.pixNum = 0
#used to display as background image
self.label = tk.Label(self)
self.label.pack(side="top", fill="both", expand=True)
self.getImages()
#### Added the GPIO event here
GPIO.add_event_callback(10, self.changeImage)
def getImages(self):
'''
Get image directory from command line or use current directory
'''
if len(sys.argv) == 2:
curr_dir = sys.argv[1]
else:
curr_dir = '.'
for root, dirs, files in os.walk(curr_dir):
for f in files:
if f.endswith(".png") or f.endswith(".jpg"):
img_path = os.path.join(root, f)
print(img_path)
self.imageList.append(img_path)
def startSlideShow(self, delay=4):
myimage = self.imageList[self.pixNum]
self.pixNum = (self.pixNum + 1) % len(self.imageList)
self.showImage(myimage)
#self.after(delay*1000, self.startSlideShow)
# while True:
# buttonState = GPIO.input(buttonPin)
# if buttonState == False:
# self.startSlideShow(self, delay=4)
##staticmethod
def changeImage(self, pull_up_down=GPIO.PUD_DOWN):
prev_input = 0
while True:
#take a reading
input = GPIO.input(10)
#if the last reading was low and this one high, print
if ((not prev_input) and input):
myimage = self.imageList[self.pixNum]
self.pixNum = (self.pixNum + 1) % len(self.imageList)
self.showImage(myimage)
#update previous input
prev_input = input
#slight pause to debounce
time.sleep(0.05)
# myimage = self.imageList[self.pixNum]
# self.pixNum = (self.pixNum + 1) % len(self.imageList)
# self.showImage(myimage)
def showImage(self, filename):
image = Image.open(filename)
img_w, img_h = image.size
scr_w, scr_h = self.winfo_screenwidth(), self.winfo_screenheight()
width, height = min(scr_w, img_w), min(scr_h, img_h)
image.thumbnail((width, height), Image.ANTIALIAS)
#set window size after scaling the original image up/down to fit screen
#removes the border on the image
scaled_w, scaled_h = image.size
self.wm_geometry("{}x{}+{}+{}".format(scaled_w,scaled_h,0,0))
# create new image
self.persistent_image = ImageTk.PhotoImage(image)
self.label.configure(image=self.persistent_image)
slideShow = HiddenRoot()
slideShow.bind("<Escape>", lambda e: slideShow.destroy()) # exit on esc
slideShow.mainloop()
root.bind('<F11>', toggle_fullscreen) # I added this in to try full screen
root.bind('<Escape>', end_fullscreen) # I added this in to try full screen
toggle_fullscreen() # I added this in to try full screen
root.mainloop() # I added this in to try full screen
GPIO.cleanup()
And from that guide I said to note earlier, here is the code they which loads a clock into fullscreen mode (and I followed their method of loading the script on boot which worked)
import tkinter as tk
import tkinter.font as tkFont
import time
###############################################################################
# Parameters and global variables
# Default font size
font_size = -24
# Declare global variables
root = None
dfont = None
frame = None
dtime = None
# Global variable to remember if we are fullscreen or windowed
fullscreen = False
###############################################################################
# Functions
# Toggle fullscreen
def toggle_fullscreen(event=None):
global root
global fullscreen
# Toggle between fullscreen and windowed modes
fullscreen = not fullscreen
root.attributes('-fullscreen', fullscreen)
resize()
# Return to windowed mode
def end_fullscreen(event=None):
global root
global fullscreen
# Turn off fullscreen mode
fullscreen = False
root.attributes('-fullscreen', False)
resize()
# Automatically resize font size based on window size
def resize(event=None):
global time_dfont
global button_dfont
global frame
# Resize font based on frame height (minimum size of 12)
# Use negative number for "pixels" instead of "points"
new_size = -max(12, int((frame.winfo_height() / 2)))
time_dfont.configure(size=new_size)
new_size = -max(12, int((frame.winfo_height() / 30)))
button_dfont.configure(size=new_size)
# Read values from the sensors at regular intervals
def update():
global root
global dtime
# Get local time
local_time = time.localtime()
# Convert time to 12 hour clock
hours = local_time.tm_hour
if hours > 12:
hours -= 12
# Add leading 0s
shours = str(hours)
smin = str(local_time.tm_min)
if hours < 10:
shours = '0' + shours
if local_time.tm_min < 10:
smin = '0' + smin
# Construct string out of time
dtime.set(shours + ':' + smin)
# Schedule the poll() function for another 500 ms from now
root.after(500, update)
###############################################################################
# Main script
# Create the main window
root = tk.Tk()
root.title("My Clock")
# Create the main container
frame = tk.Frame(root, bg='black')
# Lay out the main container (expand to fit window)
frame.pack(fill=tk.BOTH, expand=1)
# Variables for holding temperature and light data
dtime = tk.StringVar()
# Create dynamic font for text
time_dfont = tkFont.Font(family='Courier New', size=font_size)
button_dfont = tkFont.Font(size=font_size)
# Create widgets
label_time = tk.Label( frame,
textvariable=dtime,
font=time_dfont,
fg='red',
bg='black')
button_quit = tk.Button(frame,
text="Quit",
font=button_dfont,
command=root.destroy,
borderwidth=0,
highlightthickness=0,
fg='gray10',
bg='black')
# Lay out widgets in a grid in the frame
label_time.grid(row=0, column=0, padx=20, pady=20)
button_quit.grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
# Make it so that the grid cells expand out to fill window
frame.rowconfigure(0, weight=10)
frame.rowconfigure(1, weight=1)
frame.columnconfigure(0, weight=1)
# Bind F11 to toggle fullscreen and ESC to end fullscreen
root.bind('<F11>', toggle_fullscreen)
root.bind('<Escape>', end_fullscreen)
# Have the resize() function be called every time the window is resized
root.bind('<Configure>', resize)
# Schedule the poll() function to be called periodically
root.after(20, update)
# Start in fullscreen mode and run
toggle_fullscreen()
root.mainloop()
Now what I'm trying to figure out is how I can implement their method of going into a full screen display into my program
Thank you :)!
I am not sure if I really understood your question.
I understood you want to change on certain events to full screen. If yes, you just need to change the geometry property of your root. Like for example
master.geometry("{0}x{1}+0+0".format(
master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad))
above code checks for screen size and reduces some distance on w and h to fit in screen. Have a look to below link.
https://stackoverflow.com/questions/7966119/display-fullscreen-mode-on-tkinter#:~:text=This%20creates%20a%20fullscreen%20window,geometry%20and%20the%20previous%20geometry.&text=You%20can%20use%20wm_attributes%20instead%20of%20attributes%20%2C%20too.
you can create a function with that call and trigger it on start up or button pressed.
Hope my guess is right and this answers helps.
Cheers

python: missing 1 required positional argument: 'self'

I try find solution in google but all solution in google not work for me maybe here I get The correct answer.
I have this code:
from tkinter import *
class gui_main:
def __init__(self):
self.win_about = Tk() #creat new windows
self.win_about.title("About software") # Get title to new windows -> "About software"
self.win_about.geometry("400x120+600+200") # Get size to window
self.win_about.resizable(width=False, height=False) # Off option Increase / decrease window
lab = Label(self.win_about, text="""
welcome to app
For Enter to app click on button Next.
""", justify='center') # Create new text in the window
lab.place(x=-18, y=-11) # Position of text in window (x - up/down , y - left/right)
btn_next = Button(self.win_about, text="Next", fg="red", command=gui_main.screen_menu()) # Create new button
btn_next.place(x=350, y=90) # Position of button in window (x - up/down , y - left/right)
btn_exit = Button(self.win_about, text="Exit", fg="red", command=self.win_about.destroy) # Create new button
btn_exit.place(x=10, y=90) # Position of button in window (x - up/down , y - left/right)
self.win_about.mainloop() # Run the cod in loop
def screen_menu(self):
self.win_menu = Tk()
self.win_menu.title("Menu")
self.win_menu.geometry("500x500+400+400")
self.win_about.destroy()
self.win_menu.mainloop()
if __name__ == "__main__":
g = gui_main()
g.win_about()
And I get this Error:
Traceback (most recent call last): File "location file", line 42, in
g = gui_main() File "location file", line 26, in init
btn_next = Button(self.win_about, text="Next", fg="red", command=gui_main.screen_menu()) # Create new button TypeError: screen_menu() missing 1 required positional argument: 'self'
Ty for help, I will hope find any solution
the problem is you should use self instead of class name apart from that i prefer and many people prefer to use lambda methods in command=. inside class you have to call each methods and variables with self. in order to work inside class.
apart from that i made few changes in your code also.
you don't need to call g.about_screen()
since you running mainloop() inside def __init__(self): method. because its already running when you are initializing the class object here g = class_name();.
here is the code
from tkinter import *
class gui_main:
def __init__(self):
self.win_about = Tk() #creat new windows
self.win_about.title("About software") # Get title to new windows -> "About software"
self.win_about.geometry("400x120+600+200") # Get size to window
self.win_about.resizable(width=False, height=False) # Off option Increase / decrease window
lab = Label(self.win_about, text="""
welcome to app
For Enter to app click on button Next.
""", justify='center') # Create new text in the window
lab.place(x=-18, y=-11) # Position of text in window (x - up/down , y - left/right)
btn_next = Button(self.win_about, text="Next", fg="red", command=lambda:self.screen_menu()) # Create new button
btn_next.place(x=350, y=90) # Position of button in window (x - up/down , y - left/right)
btn_exit = Button(self.win_about, text="Exit", fg="red", command=lambda:self.quit()) # Create new button
btn_exit.place(x=10, y=90) # Position of button in window (x - up/down , y - left/right)
self.win_about.mainloop() # Run the cod in loop
def quit(self):
self.win_about.quit()
def screen_menu(self):
self.win_menu = Tk()
self.win_menu.title("Menu")
self.win_menu.geometry("500x500+400+400")
# self.win_about.destroy()
self.win_menu.mainloop()
if __name__ == "__main__":
g = gui_main()
Remove the parenthesis from the Button command and refer to self instead of gui_main
btn_next = Button(self.win_about, text="Next", fg="red", command=self.screen_menu) # Create new button
You want to pass the callable itself, not the return value of gui_main.screen_menu

Way to avoid having multiple windows when using Messagebox (or alternative to it)?

I'm trying to write my first GUI based python program using Tkinter. I have created a base window which holds the menu bar with a couple of options.
One of the options is for a standard 'About' box. When I call the about section with
helpMainMenu.add_command(label="About", command=self.aboutProgram)
It opens the message box, but in a fresh window so there are now two windows showing on the taskbar.
Is there any way to stop it opening a new window and use the main one instead, or is there a better way to do it?
The full code is below
#! /usr/bin/python3
from tkinter import *
from tkinter import messagebox
import datetime
timeNow = datetime.datetime.now()
writeYear = 2020 # Enter the year you started writing the program
lineFeed = "\n"
programTitle = "Basic Menu"
programVersion = "Version 1.0.0"
programmerName = " Name (email#gmail.com)"
if timeNow.year > writeYear:
programAuthor = "©" + str(writeYear) + "-" + str(timeNow.year) + programmerName
else:
programAuthor = "©" + str(writeYear) + programmerName
aboutMessage = programTitle + lineFeed + programVersion + lineFeed + programAuthor
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("{} ({})".format(programTitle, programVersion))
self.pack(fill=BOTH, expand=1)
menu = Menu(self.master)
self.master.config(menu=menu)
fileMainMenu = Menu(menu, tearoff=0) #Create the File menu container
fileMainMenu.add_command(label="Exit", command=self.programExit) # File menu option
menu.add_cascade(label="File", menu=fileMainMenu)
helpMainMenu = Menu(menu, tearoff=0) #Create the Help menu container
helpMainMenu.add_command(label="About", command=self.aboutProgram)
menu.add_cascade(label="Help", menu=helpMainMenu)
def programExit(self):
exitMsgBox = messagebox.askquestion ("Exit Application","Are you sure you want to exit the application",icon = "warning")
if exitMsgBox == "yes":
root.destroy()
exit()
def aboutProgram(self):
messagebox.showinfo("About","About the application", icon = "info")
root = Tk() # root window created. Here, that would be the only window, but
windowHeight = int(root.winfo_screenheight()/100*75) # Set the main window height to 75% of the screen height
windowWidth = int(root.winfo_screenwidth()/100*75) # Set the main window width to 75% of the screen width
screenWidth = int(root.winfo_screenwidth())
screenHeight = int(root.winfo_screenheight())
positionRight = int(root.winfo_screenwidth()/2 - windowWidth/2) # Get the screen width and divide by 2, then minus the result of 'windowWidth' divided by 2
positionDown = int(root.winfo_screenheight()/2 - windowHeight/2) # Get the screen height and divide by 2, then minus the result of 'windowHeight' divided by 2
root.geometry("{}x{}+{}+{}".format(windowWidth, windowHeight, positionRight, positionDown)) # Positions the window in the center of the page.
app = Window(root)
root.mainloop()
Python Version 3.7.3
tkinter.TkVersion 8.6
The simplest way would be to create a new frame for the "about" page, and then overlay it on top of the main window with place -- one of the few times when place is superior to grid and pack.
You should also do a "grab" on the frame so that all events are funneled to the frame and its children. With a grab, while the popup is visible you can't interact with the widgets on the main window.
Here's a quick example:
def aboutProgram(self):
# create the frame with a message and a button
# which destroys the window
aboutFrame = Frame(self.master, bd=2, relief="groove")
label = Label(aboutFrame, text="About the application...")
button = Button(aboutFrame, text="Ok", command=aboutFrame.destroy)
label.pack(side="top", padx=20, pady=20)
button.pack(side="bottom", pady=20)
# overlay the "about" page on top of the root window
aboutFrame.place(relx=.5, rely=.5, anchor="c")
# force all events to go to the popup
aboutFrame.grab_set()
If you want to completely hide the contents of the main window, you can change the place arguments to fill the window:
aboutFrame.place(x=0, y=0, anchor="nw", relwidth=1.0, relheight=1.0)

Categories

Resources