How to set time.sleep for different widgets - python

There is code that checks the availability of sites.
How can we make the status for each site to change at a user defined time (i.e. the time for each site can be different) The problem is that the number of sites is not limited, because you can add more lines to the application, so I do not understand how to implement it.
I attach a picture of how it looks like:
Code:
import tkinter as tk
from tkinter import ttk
import requests
import time
from tkinter import *
from tkinter import messagebox
data_list = []
window = Tk()
window.geometry('400x700')
window.title("SiteChecker")
def set_input(obj, value):
obj.delete(1.0, "END")
obj.insert("END", value)
def SiteCheck():
# time.sleep
for data in data_list:
url = data[0].get()
status = data[2]
if not str(url).startswith('http'):
continue
print(url)
Get_Response = None
try:
Get_Response = requests.get(url)
except:
status.config(text='status bad')
continue
if Get_Response.status_code == 200:
status.config(text='status ok')
pass
implement
else:
status.config(text='status bad')
def clicked():
txt = Entry(window, width=18)
txt.grid(column=0, pady=8)
txt_row = txt.grid_info()['row']
tim = Entry(window, width=3)
tim.grid(row=txt_row, column=1, pady=8)
txt_row = tim.grid_info()['row']
result1 = Label(window, text="status")
result1.grid(row=txt_row, column=2, pady=8)
data_list.append([txt, tim, result1])
lbl1 = Label(window, text="Enter references:")
lbl1.grid(column=0, row=1)
lbl2 = Label(window, text="Enter the test time: ")
lbl2.grid(column=1, row=1)
lbl3 = Label(window, text="Availability status ")
lbl3.grid(column=2, row=1)
for loop in range(2, 6):
txt1 = Entry(window, width=18)
txt1.grid(column=0, row=loop, pady=8)
tim1 = Entry(window, width=3)
tim1.grid(column=1, row=loop, pady=8)
result1 = Label(window, text="status")
result1.grid(column=2, row=loop, pady=8)
data_list.append([txt1, tim1, result1])
btn = Button(window, text="Add another site", command=clicked)
btn.grid(column=1, row=0)
Check_Button = Button(
window,
command=SiteCheck,
text='Start checking',
)
Check_Button.grid(row=0, column=2)
window.mainloop()

See here (How do I make my function run every second) how to use tkinter after() to achieve what you want. time.sleep won't work for your purpose because it is blocking the execution of the entire code.
From the link given in the comment to your question by Patrick Artner :
Tkinter root windows have a method called after() which can be used to schedule a function to be called after a given period of time. If that function itself calls after() you've set up an automatically recurring event.

Related

How to populate one entry widget based on what you type in another entry widget

So I have two Entry fields, one for a user to enter number and the second one is for displaying the square of the number entered. The approach I would like is that when the user starts typing in the number in the first widget, the second widget should be updated with the corresponding square of the number being typed in the first widget.
Here is my GUI
Now this is my code but it is not working as I expect. Please help me understand how to go about this problem without involving user of a button.
import tkinter as tk
from tkinter import *
def keyPressed(event):
#key = entry.get(event.char)
key=entry.get()
if key.isdigit():
ans_txt.delete(0, END)
ans_txt.insert(0,key)
print(key, " success")
else:
print("fail")
app=Tk()
app.geometry("400x350")
ent_lbl=Label(app, text="NUMBER: ", padx=3, pady=3)
ent_lbl.grid(column=0, row=0)
entry = tk.Entry(width=15)
entry.bind("<Key>", keyPressed)
entry.grid(column=1, row=0, padx=20, pady=20)
ans_lbl=Label(app, text="SQUARE: ", padx=3, pady=3)
ans_lbl.grid(column=0, row=20)
ans_txt=tk.Entry(app, width=15)
ans_txt.grid(column=1, row=20)
app.mainloop()
You should use the .trace method of the Entry widget. You can catch the "writing" event with the trace method and you can call a callback function with that method. Doc of trace: http://mgltools.scripps.edu/api/DejaVu/Tkinter.Variable-class.html
Furthermore you has to use the IntVar() to show (and calculate) the numbers in the resul Entry widget. Doc of IntVar: http://epydoc.sourceforge.net/stdlib/Tkinter.IntVar-class.html
Complete code:
import tkinter as tk
from tkinter import *
app = Tk()
app.geometry("400x350")
input_var = tk.IntVar()
Label(app, text="NUMBER: ", padx=3, pady=3).grid(column=0, row=0)
input_entry = tk.Entry(width=15, textvariable=input_var)
input_entry.grid(column=1, row=0, padx=20, pady=20)
result_var = tk.IntVar()
Label(app, text="SQUARE: ", padx=3, pady=3).grid(column=0, row=20)
output_entry = tk.Entry(app, width=15, textvariable=result_var)
output_entry.grid(column=1, row=20)
def key_pressed(name, index, mode):
output_entry.delete(0, END)
try:
output_entry.insert(0, int(input_entry.get()) ** 2)
except Exception:
output_entry.insert(0, "Wrong Input")
output_entry.delete(0, END) # Shouldn't show trailing zero when starting the GUI
input_entry.delete(0, END) # Shouldn't show trailing zero when starting the GUI
input_var.trace("w", key_pressed)
result_var.trace("w", key_pressed)
app.mainloop()
Output:
Error handling:
Please Check this out
You can use Tkinter's trace mechanism to watch the variables associated with your Entry widgets. Whenever the Entry values change the Entry will automatically update.
import tkinter as tk
from tkinter import *
app=Tk()
app.geometry("400x350")
var1= tk.IntVar()
ent_lbl=Label(app, text="NUMBER: ", padx=3, pady=3)
ent_lbl.grid(column=0, row=0)
entry = tk.Entry(width=15,textvariable=var1)
entry.grid(column=1, row=0, padx=20, pady=20)
result = tk.IntVar()
ans_lbl=Label(app, text="SQUARE: ", padx=3, pady=3)
ans_lbl.grid(column=0, row=20)
ans_txt=tk.Entry(app, width=15,textvariable=result)
ans_txt.grid(column=1, row=20)
def keyPressed(name, index, mode):
#key = entry.get(event.char)
key=entry.get()
if key.isdigit():
ans_txt.delete(0, END)
ans_txt.insert(0,int(key)**2)
print(key, " success")
else:
print("fail")
var1.trace('w', keyPressed)
result.trace('w', keyPressed)
app.mainloop()

Copying text in tkinter from label or msgbeox

I been searching for methods to copy text to clipboard or copy the results from Tkinter gui but idk if there is a command or something
here is my code for now here the result comes in a messagebox can i copy it to clipboard
import tkinter.messagebox
import string
import random
def qs_msgbbox(): # qs_msgbbox
tkinter.messagebox.showinfo("Info", "For customer support or tip or rating contact:"
"dghaily725#gmail.com\npress the button for generated pass\nmsg will appear then copy\nthe generated password")
def gen_pass(k=9): # gen_pass
char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*"
password = ''
for i in range(9):
password += random.choice(char)
tkinter.messagebox.showinfo("Password", password)
root = Tk()
root.title("Password Generator")
lbl1 = Label(root, text="Generate Password", bd=2, relief=SUNKEN, height=5, width=50, bg='black', fg='white')
lbl1.configure(font=(70))
lbl1.grid(row=0, column=2)
lbl2 = Label(root, text='For more information press the Question mark', bd=2, relief=SUNKEN, fg='red')
lbl2.configure(font=(70))
lbl2.grid(row=0, column=0, pady=10)
btn1 = Button(root, text='Press to Generate', height=5, width=50, bg='grey', command=gen_pass)
btn1.configure(font=(70))
btn1.grid(row=1, column=2, padx=460, pady=50)
btn2photo = PhotoImage(file='question.png')
btn2 = Button(root, image=btn2photo, width=30, height=30, command= qs_msgbbox)
btn2.grid(row=0, column=1)
root.mainloop()
and also just a quick small question is it better to use classes or this form
Tkinter does have a function for that, simply just
from tkinter import Tk
root = Tk()
root.clipboard_clear()
root.clipboard_append("Something to the clipboard")
root.update() # the text will stay there after the window is closed
Hope I could help
Greets
The above answer is perfectly fine. Infact its the method to do it. I read the comments, He had mentioned that it could only take in string. That is completely false. It can also take in functions. For example..
import tkinter as tk
root = tk.Tk()
#creating a entry Widget.(Labels are fine as well)
entry = tk.Entry(root)
entry.pack()
#NOW if you want to copy the whole string inside the above entry box after you
typed in #
def copy ():#assign this function to any button or any actions
root.clipboard_clear()
root.clipboard_append(entry.get()) #get anything from the entry widget.
root.mainloop()
Hoping this was helpful

how to get input from a tkinter text widget when its inside a function

relatively new to coding and currently I am playing with tkinter in python, I am using a text widget within a function and want to send the input from the text box to another function. My global variable says undefined at module level, so How could I make it defined at a module level if its within a function?
When I press the send email button I get this error message "NameError: name 'user_message_entry' is not defined"
Any suggestions? Many thanks!
minimum reproduction:
import tkinter as tk
root = tk.Tk()
root.geometry("500x500")
def send_email():
global user_message_entry
subject = ":)"
body = user_message_entry.get("1.0", "end")
message = f"subject: {subject}\n\n {body}"
print(message)
def feedback():
feedback_window = tk.Toplevel()
feedback_window.geometry("690x650")
message_frame = tk.Frame(feedback_window)
message_frame.grid(row=0, column=0, columnspan=3)
user_message_entry = tk.Text(message_frame, height=10, width=60)
user_message_entry.grid(row=0, column=0)
send_email_button = tk.Button(feedback_window, command=send_email,
height=20, width=20, bg="yellow", text="send email")
send_email_button.grid(row=1, column=0)
open_feedback_button = tk.Button(root, command=feedback, height=20, width=20, bg="yellow", text="open feedback window")
open_feedback_button.grid(row=1, column=0)
root.mainloop()
You can use Object orient methodology to make access sympler, another option also you can use globals() to make variable global
One way
globals()['user_message_entry'] = tk.Text(message_frame, height=10, width=60)
....
and from another function you can call
body = globals()['user_message_entry'].get("1.0", "end")
Second way
Object oriented programming is good for every type of problem solving, so you can use class as well
import tkinter as tk
class CBased:
def __init__(self, master, *args, **kwargs):
super(CBased, self).__init__(*args, *kwargs)
self.master = master
master.geometry("500x500")
self.open_feedback_button = tk.Button(master, command=self.feedback, height=20, width=20, bg="yellow", text="open feedback window")
self.open_feedback_button.grid(row=1, column=0)
def send_email(self):
subject = ":)"
body = self.user_message_entry.get("1.0", "end")
message = f"subject: {subject}\n\n {body}"
print(message)
def feedback(self):
self.feedback_window = tk.Toplevel()
self.feedback_window.geometry("690x650")
self.message_frame = tk.Frame(self.feedback_window)
self.message_frame.grid(row=0, column=0, columnspan=3)
self.user_message_entry = tk.Text(self.message_frame, height=10, width=60)
self.user_message_entry.grid(row=0, column=0)
self.send_email_button = tk.Button(self.feedback_window, command=send_email,
height=20, width=20, bg="yellow", text="send email")
self.send_email_button.grid(row=1, column=0)
def main():
root = Tk()
myobj = CBased(root)
root.mainloop()
if __name__ == "__main__":main()
In this way you can call every single item by self.xyz

How do you use tkinter to display the output of a function call?

I'm trying to use using tkinter to demonstrate the functionality of a given python library. The GUI must take textual input from the user, await a button push, send the input to the function, display the result, and repeat this process every time the user pushes the button.
import tkinter as tk
def do_something(phrase):
return phrase + phrase
def main():
root = tk.Tk()
root.title("Demo")
tk.Label(root, text="Please enter a sentence: ").grid(row=0)
user_input = tk.Entry(root)
user_input.grid(row=0, column=1)
result = tk.Button(root, text='Do something', command=do_something(user_input.get())).grid(row=1, column=1, sticky=tk.W, pady=4)
tk.Label(root, text=result).grid(row=2, column=1)
root.mainloop()
if __name__ == "__main__":
main()
I don't know how to access the value returned by do_something(). I imagine that once I understand how to do that, there might be the issue of ensuring that the process can be repeated as many times as the window remains open and the user presses the button.
Guess that you want to set the text of the last label based on the input value of user_input. You can do it as below:
import tkinter as tk
def do_something(phrase):
return phrase + phrase
def main():
root = tk.Tk()
root.title("Demo")
tk.Label(root, text="Please enter a sentence: ").grid(row=0)
user_input = tk.Entry(root)
user_input.grid(row=0, column=1)
result = tk.Label(root, text='')
result.grid(row=2, column=0, columnspan=2)
btn = tk.Button(root, text='Do something')
btn.config(command=lambda: result.config(text=do_something(user_input.get())))
btn.grid(row=1, column=1, sticky=tk.W, pady=4)
root.mainloop()
if __name__ == "__main__":
main()

Python GUI using Tkinter how to print input exactly the way you enter them?

I'm exploring tkinter as of now and trying to do sample exercises I can think of. What I want is when I enter an input like this:
I've
entered
this
I want to display them that way as well but I'm only getting this:
I'veenteredthis
This is a snippet from my code for this part:
input = textBox.get("1.0", 'end-1c')
logBox.insert(tk.END, input)
I've tried doing these:
input = input.replace("\n", "\n"), logBox.insert(tk.END, input+ "\n")
Please do understand that I'm not well equipped with knowledge in Python as I am still trying to learn the language. Thank you in advance!
Edit: Here is the full code just don't mind the other parts since I'm trying to do something
import sys
import os
import time
import operator
import tkinter as tk
from tkinter import *
def test():
input = textBox.get("1.0", 'end-1c')
# input = input.replace("\n", "\n")
logBox.insert(tk.END, input+ "\n")
window = tk.Tk()
window.geometry("{0}x{1}+0+0".format(window.winfo_screenwidth(),
window.winfo_screenheight()))
window.title("Test")
mainFrame = Frame(window, width=8000, height=8000)
mainFrame.pack(side=TOP)
LabelText = Label(mainFrame, text="Type your text below:", anchor='center', pady=10)
LabelText.pack()
textBox = tk.Text (mainFrame, font=('averdana', 10), height=18, width=180)
textBox.pack()
BTNRun = Button(mainFrame, text="Run", height=1, width=10,
command=test)
BTNRun.pack(padx=10, pady=10)
LogText = Label(mainFrame, text="Console Log", anchor='ne', pady=10)
LogText.pack()
logBox = tk.Listbox(mainFrame, font=('averdana', 10), height=10, width=180)
logBox.pack()
BTNExit = Button(mainFrame, text="Exit", height=1, width=10, command=quit)
BTNExit.pack()
window.mainloop()```
Do not name a variable input. input is a built in method of python. That said you need to split the string at the line breaks so use split() and then input the resulting list.
Change this:
def test():
input = textBox.get("1.0", 'end-1c')
# input = input.replace("\n", "\n")
logBox.insert(tk.END, input+ "\n")
To this:
# had to update this function my original answer had some issues
def test():
my_input = textBox.get("1.0", 'end-1c')
x = my_input.split("\n")
for item in x:
logBox.insert(tk.END, item.strip())

Categories

Resources