End multi scripts running on tkinter - python

I am trying to end the process of multi-scripts running on tkinter by a click of the end process created button. However, this does not seem to work when any of the scripts are running in an infinite loop to stop the process.
Here is my code:
import os
import sys
from tkinter import *
import tkinter.messagebox as tkmsg
root = Tk(className=" x") # creates root window
# all components of thw window will come here
Label(root,text='Enter Load Value or Choose a test action',font=("Helvetica", 16), width=40, height=2).pack(side=TOP)
svalue = StringVar() # defines the widget state as string
w = Entry(root,textvariable=svalue).pack(side=LEFT,padx=10) # adds a textarea widget
def act():
print ("Value entered")
print ('%s' % svalue.get())
def script_1():
os.system('python script1_1.py')
def script_2():
os.system('python script1_2.py')
global root
while 1:
root.update()
pass
def script_3():
os.system('python script1_3.py')
def script_4():
os.system('python script1_4.py')
def script_5():
os.system('python script1_5.py')
def quit():
tkmsg.showinfo("Stopped", "Stopped")
sys.exit
if __name__ == '__main__':
global root
root = Frame ()
root.pack ()
button0 = Button(root,text="Load", command=act).pack(side=LEFT,padx=10)
button1 = Button(root,text="Test 1",command=script_1).pack(side=LEFT,padx=10)
button2 = Button(root,text="Test 2",command=script_2).pack(side=LEFT,padx=10)
button3 = Button(root,text="Test 3",command=script_3).pack(side=LEFT,padx=10)
button4 = Button(root,text="Test 4",command=script_4).pack(side=LEFT,padx=10)
button5 = Button(root,text="Test 5",command=script_5).pack(side=LEFT,padx=10)
button6 = Button(root,fg="red",text="End process",command=quit).pack(side=LEFT,padx=10)
button.mainloop() # an event loop to invoke custom function "act"
root.mainloop() # To keep GUI window running

Related

on a button click, copy whats inside entry() and store it to a variable (tkinter)

I have two widgets to work with, a text input, and a button, both are created inside a function. What I want to happen is the user types in their name and then clicks the button to submit the answer. What I want the computer to do, is on the button press it will read whats inside the text and the save it to a variable. Once it saves it, it will print it out.
The code below is bad because it runs through the if statement immediately without the consulting of the button press.
There has to be a simpler solution. Also this may not be PEP 8 or whatever please be patient because I'm new.
import tkinter as tk
from tkinter import Tk, Label, Button
import sys
import time
import random
import threading
from tkinter import *
window = tk.Tk()
window.geometry("300x300")
window.title("GUI")
def start_screen():
reset()
start = tk.Label(window, text="start of game")
start.place(x=110,y=20)
play = Button(window, text= "play", command = start_game)
play.place(x=110,y=50)
helper = Button(window, text="help", command = help_screen)
helper.place(x=110,y=70)
def stuff():
global t
t = True
print(t)
return t
def text_handling():
global t
t = False
reset()#clears the screen
label = Label(window, text='')
question1= "what is your name?"
label.pack()
print_slow(label, question1, 40)#prints out letters slowly
#here is the part I'm having problems with
name = Entry(window)
name.pack()
but = Button(window, text="enter", command= stuff)
but.pack()
print(t)
if t == True:
myPlayer.name = name.get()
print(myPlayer.name)
def start_game():
reset()
bt = tk.Button(window,text="Enter", bg="orange", command =
text_handling)
bt.place(x=100,y=100)
start_screen()

Python tkinter: why does he want to quit?

I would need a bit of help with my code I'm writing... and although when I start the code then comes directly such a window which asks me if I want to close it.
Does anyone have an idea where this could come from?
The code should open a window where I have some buttons to open some other windows with sliders to control DMX Lights.
Here is the code:
import tkinter as tk
from tkinter import ttk
from tkinter import *
from print_dict import pd
from time import sleep
from tkinter import messagebox
Pultdatas = {'DMXtype':512,
'columns':2,
'rows':8,
'slider':8,
'modes':4
}
root = Tk()
root.configure(background='gray')
root.title('DMX-Pult v2')
Screens = {'mainscreen':[root,{}]}
def on_closing(screen):
if messagebox.askokcancel("Quit", f"Do you want to quit Scanner {screen}?"):
Screens[screen][0].destroy()
def setmode(screen,mode):
print(f'setmode on screen {screen} to {mode}')
for i in Screens[screen][1]['modesel']:
print(i)
i.config(bg='gray')
Screens[screen][1]['modesel'][mode].config(bg='green')
def pressed(btn):
print('pressed Button: ' + str(btn))
if not Screens.__contains__(btn):
Screens[btn] = []
Screens[btn].append(Tk())
Screens[btn][0].configure(background='gray')
Screens[btn][0].title(f'Scanner {btn}')
Screens[btn].append({})
Screens[btn][1]['modesel'] = []
for i in range(Pultdatas['modes']):
Screens[btn][1]['modesel'].append(Button(Screens[btn][0], text=f"mode {i+1}", bg='gray', fg='white', command=lambda name = i:setmode(btn,name)))
Screens[btn][1]['modesel'][i].grid(row=i,column=0)
setmode(btn,0)
else:
if Screens[btn][0].winfo_exists() == 1:
sleep(0.2)
print('This window exist.')
Screens[btn][0].attributes('-topmost', True)
Screens[btn][0].update()
Screens[btn][0].attributes('-topmost', False)
else:
Screens[btn] = []
Screens[btn].append(Tk())
Screens[btn][0].configure(background='gray')
Screens[btn][0].title(f'Scanner {btn}')
Screens[btn].append({})
Screens[btn][1]['modesel'] = []
for i in range(Pultdatas['modes']):
Screens[btn][1]['modesel'].append(Button(Screens[btn][0], text=f"mode {i + 1}", bg='gray', fg='white',
command=lambda name=i: setmode(btn, name)))
Screens[btn][1]['modesel'][i].grid(row=i, column=0)
Screens[btn][0].protocol("WM_DELETE_WINDOW", lambda name = btn:on_closing(name))
setmode(btn, 0)
print()
def close():
if messagebox.askokcancel("Quit", f"Do you want to quit?"):
for screen in Screens:
print(f'closed {Screens[screen][0].title()} Succesfully')
Screens[screen][0].destroy()
tmpint = 0
Screens['mainscreen'][1]['Back'] = Button(root, text='close all',bg='gray',fg='white',command=close)
Screens['mainscreen'][1]['Back'].grid(row=0,column=0)
for column in range(Pultdatas['columns']):
for row in range(Pultdatas['rows']):
tmpint += 1
Screens['mainscreen'][1][tmpint] = Button(root, text=f"Scanner {tmpint}", bg='gray', fg='white', command=lambda name = tmpint:pressed(name))
Screens['mainscreen'][1][tmpint].grid(row=row+1,column=column)
pd(Screens)
root.protocol("WM_DELETE_WINDOW", close())
root.mainloop()
You can just change this line of code
root.protocol("WM_DELETE_WINDOW", close())
To this:
root.protocol("WM_DELETE_WINDOW", close)
You don't need to write (), we can just write handler not as function.
For more info you can visit here

use a while true loop while the code below is still running (python)

Im making this game called:
IDLE PEN ,(MAKE PENS)
and every 1 second i get a bonus pen
how i get a bonus pen is doing this
Import time
While true
make a pen()
time.sleep(1)
but i have some code under the while true loop.
the code under the while true loop is like buttons to
upgrade the pens or make a pen
So how do i make the code under the while true loop work?
This is my game im happy for anyone to copy it
its not ready yet
import functools
import tkinter
import tkinter.messagebox
import time
from random import seed
from random import randint
# eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
window = tkinter.Tk()
window.title('Idle Pen')
def print_pen(number: int):
return f"Pens: {number}"
class pencount:
def __init__(self):
self.pencount = 0
self.text = tkinter.Text(height=1, width=30)
self.text.insert("1.0", print_pen(0))
self.text['state'] = 'disabled'
self.text.pack()
def changepencount(self, count):
if self.pencount + count < 0:
return
self.pencount = self.pencount + count
self.text['state'] = 'normal'
self.text.delete("1.0", "end")
self.text.insert("1.0", print_pen(self.pencount))
self.text['state'] = 'disabled'
self.text.pack()
pen = pencount()
changepenup = functools.partial(pen.changepencount, 1)
B = tkinter.Button(window, text="Make Pen", command=changepenup)
changependown = functools.partial(pen.changepencount, -100)
A = tkinter.Button(window, text='Penmaker', command=changependown)
Q = tkinter.Button(window, text="Quit", command=window.destroy)
U = tkinter.Button
# eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
B.pack()
A.pack()
Q.pack()
window.mainloop()
You could use threading to run your loop in separated thread and then main thread may run tkitner
OR you can use tkinter function after() (instead of while True) to run function with delay and this function should use again after() to run itself.
import tkinter as tk
# --- functions ---
def update():
global value
value += 1
text = f'make penny: {value}'
print(text)
label['text'] = text
# run again after 1s (1000ms)
root.after(1000, update)
# --- main ---
value = 0
root = tk.Tk()
label = tk.Label(root, text="make penny: 0")
label.pack()
button = tk.Button(root, text="Exit", command=root.destroy)
button.pack()
# run first time after 1s (1000ms)
root.after(1000, update)
root.mainloop()

Tkinter class function causing an error when trying to utilize the entry widget

Please help me with this error. I am very confused as to why I cannot reference and obtain the contents of the entry. If someone can please help, it will be very greatly appreciated. If you need anymore context on what the problem is, please leave a comment.
When I run the program I get an error which says
self.file_location = file_location_entry.get()
NameError: name 'file_location_entry' is not defined
I am confused for getting this error since I have defined this variable below inside of the class in the main initializer function.
# Imports
import tkinter as tk
from tkinter import ttk
# ==================================================================================================
class GUI():
# Global variable for file location of software to scan
global file_location
# ==================================================================================================
# Button Functions for Windows
# Function used to open other window that will be used for the script based attacks
def script_attack_window(self):
pass
# Close Window Button Command
def close_window(self, window):
return window.quit
# Start Audit Button Command
def start_audit(self):
#function to start the security audit
pass
# Display Text To Textbox Command
def display_text_to_textbox(self, text):
self.display_textbox.insert(tk.END, text)
def set_variable(self):
self.file_location = self.file_location_entry.get()
self.display_text_to_textbox(self.file_location)
# Window for entering default location for auditing tool
def default_location_auditing_tool_window(self):
pass
# ==================================================================================================
# Main Window Function
# Rescource for using frames to organize the window better
# https://stackoverflow.com/questions/2261191/how-can-i-put-2-buttons-next-to-each-other
# https://www.tutorialspoint.com/python/tk_frame.htm
# https://realpython.com/python-gui-tkinter/
# https://tkdocs.com/tutorial/
# This will be used to display the main menu when called
def __init__(self):
# Initializing a new window
root = tk.Tk()
root.title("Main Menu")
# Making frames
canvas = tk.Frame()
blocked_space = tk.Frame(canvas)
# Initializing the window settings
root.attributes('-type', 'dialog')
#=======================Buttons=========================
# Button to start the autiting software
auditing_button = tk.Button(master=canvas, text="Audit", command=self.start_audit())
# Button to close the window
close_button = tk.Button(master=canvas, text="Close", command=self.close_window(root))
# Button to open script page
script_button = tk.Button(master=canvas, text="Script Attack", command=self.script_attack_window())
# Button to set the file variable
file_enter_button = tk.Button(master=canvas, text="Enter File Path", command=self.set_variable())
# Textbox for getting user input for file location
self.file_location_entry= tk.Entry(master=canvas)
# TextBox for displaying the text
self.display_textbox = tk.Text(master=canvas)
# Plotting the buttons and textboxes and entry on the grid
canvas.grid(column=0, row=0)
auditing_button.grid(row=3, column=1)
auditing_button.columnconfigure(1, weight=1)
close_button.grid(row=3, column=0)
close_button.columnconfigure(0, weight=1)
script_button.grid(row=3, column=2)
script_button.columnconfigure(2, weight=1)
file_enter_button.grid(column=0, row=0)
self.file_location_entry.grid(column=0, row=1, columnspan=3, sticky="ewn")
self.display_textbox.grid(column=3, row=1)
# Starting the window mainloop
root.mainloop()
# ==================================================================================================
# ---------------------------------------------------------------------------------------------------
x = GUI()
~ ```
I think that the problem is in the order in which you write the code.
Below I've rewritten your script in full OO mode, that's mean without the use
of the global variable and the double passage to assign to the text the value
of the entry variable and with the right sequence, first the app callbacks and
app variables, after GUI init, and finally the callbacks.
#!/usr/bin/python3
import sys
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
class App(tk.Tk):
"""Main Application start here"""
def __init__(self):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_close)
self.title("Simple App")
#never use global...
self.text = tk.StringVar()
self.init_ui()
def init_ui(self):
w = ttk.Frame(self, padding=5)
r = 0
c = 0
self.file_location_entry = ttk.Entry(w,
justify=tk.LEFT,
textvariable=self.text)
self.file_location_entry.grid(row=r, column=c, sticky=tk.W+tk.E, padx=5, pady=5)
r += 1
self.display_textbox = tk.Text(w)
self.display_textbox.grid(row=r, column=c, padx=5, pady=5)
r = 0
c = 1
b = ttk.LabelFrame(self, text="", relief=tk.GROOVE, padding=5)
bts = [("Audit", 1, self.start_audit, "<Alt-a>"),
("Enter File Path", 0, self.set_variable, "<Alt-e>"),
("Script Attack", 0, self.script_attack_window, "<Alt-s>"),
("Close", 0, self.on_close, "<Alt-c>")]
for btn in bts:
ttk.Button(b, text=btn[0], underline=btn[1], command = btn[2]).grid(row=r,
column=c,
sticky=tk.N+tk.W+tk.E,
padx=5, pady=5)
self.bind(btn[3], btn[2])
r += 1
b.grid(row=0, column=1, sticky=tk.N+tk.S)
w.grid(row=0, column=0, sticky=tk.N+tk.W+tk.S+tk.E)
def start_audit(self, evt=None):
pass
def script_attack_window(self, evt=None):
pass
def set_variable(self, evt=None):
self.display_textbox.insert(tk.END, self.text.get())
def on_close(self,evt=None):
"""Close all"""
if messagebox.askokcancel(self.title(), "Do you want to quit?", parent=self):
self.destroy()
def main():
app = App()
app.mainloop()
if __name__ == '__main__':
main()

tkinkter thread not terminating (gif runs in endless loop)

I'm trying to link 2 actions with the pressing of a button. I'm using threading
One function 'callback' prints a message, and another one creates a label that
displays a gif animation. When I try to thread them and press the button to run
them, the gif is displayed infinitely (continously), but I'd like to have it
removed (deleted) from the GUI as soon 'callback' finishes running. Any help is appreciated.
from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
import threading
import time
root = Tk()
root.title('Title')
def callback():
print('this message')
time.sleep(0.5)
def animate():
while True:
try:
time.sleep(0.04)
img = PhotoImage(file='path',format="gif - {}".format(num))
label1 = ttk.Label(root, image=img)
label1.grid(row=0, column=1)
num+=1
except:
num=0
def thr():
t1= threading.Thread(target=callback)
t2= threading.Thread(target=animate)
t1.start()
t2.start()
button = ttk.Button(root, text='click', command=thr).grid(row=0, column=1, sticky=N)
entry = scrolledtext.ScrolledText(root, width=30, heigh=10, wrap=WORD)
entry.grid(row=0, column=0)
entry.focus()
root.mainloop()
You can use variable to inform second thread that first thread ends.
running = False
But it can be not the best method - maybe you should rather use module queue to send information from one thread to another.
You can use label1.destroy() to remove label and image but you have to create label only once and later only change image in this label.
label1['image'] = img
Code:
from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
import threading
import time
#from PIL import Image, ImageTk # for `png`
# --- functions ----
def callback():
# inform function to use external/global variable because you use `=`
global running
print('callback: start')
time.sleep(2)
print('callback: end')
# inform other thread to end running
running = False
def animate():
print('animate: start')
while running:
try:
time.sleep(0.04)
img = PhotoImage(file='path', format="gif - {}".format(num))
#img = Image.open('test/image-{}.png'.format(num)) # for `png`
#img = ImageTk.PhotoImage(img) # for `png`
#label1.img = img # solution for garbage collector problem # for `png`
label1['image'] = img
num += 1
except:
num = 0
#label1.img = None # doesn't work
#label1['image'] = None # doesn't work
# destroy label
label1.destroy()
print('animate: end')
def thr():
# inform function to use external/global variable because you use `=`
global running
global label1
# create new label
label1 = ttk.Label(root)
label1.grid(row=0, column=1)
running = True
t1 = threading.Thread(target=callback)
t2 = threading.Thread(target=animate)
t1.start()
t2.start()
# --- main ---
# create global variables
running = False
label1 = None
# - GUI -
root = Tk()
root.title('Title')
button = ttk.Button(root, text='click', command=thr)
button.grid(row=0, column=1, sticky=N)
entry = scrolledtext.ScrolledText(root, width=30, heigh=10, wrap=WORD)
entry.grid(row=0, column=0)
entry.focus()
root.mainloop()
EDIT: you could also use
while t1.is_alive():
instead of while running:
EDIT: you can also use root.after isntead of second thread.
from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
import threading
import time
#from PIL import Image, ImageTk # for `png`
# --- functions ----
def callback():
# inform function to use external/global variable because you use `=`
global running
print('callback: start')
time.sleep(2)
print('callback: end')
def animate(num=0):
try:
img = PhotoImage(file='path', format="gif - {}".format(num))
#img = Image.open('test/ball-{}.png'.format(num)) # for `png`
#img = ImageTk.PhotoImage(img) # for `png`
#label1.img = img # solution for garbage collector problem # for `png`
label1['image'] = img
num += 1
except:
num = 0
if t1.is_alive():
# execute again after 4ms
root.after(4, animate, num) # 4ms = 0.04s
else:
# destroy label
label1.destroy()
print("animate: end")
def thr():
# inform function to use external/global variable because you use `=`
global label1
global t1
# create new label
label1 = ttk.Label(root)
label1.grid(row=0, column=1)
t1 = threading.Thread(target=callback)
t1.start()
print("animate: start")
animate(0)
# --- main ---
# create global variables
label1 = None
t1 = None
# - GUI -
root = Tk()
root.title('Title')
button = ttk.Button(root, text='click', command=thr)
button.grid(row=0, column=1, sticky=N)
entry = scrolledtext.ScrolledText(root, width=30, heigh=10, wrap=WORD)
entry.grid(row=0, column=0)
entry.focus()
root.mainloop()

Categories

Resources