With this code I was able to create a TK Inter pop-up with a button to run a Sample_Function.
This Sample_Function destroys the tk pop-up, runs another python file, and then opens itself (the first pop-up) again.
How can I run the other_python_file and pop-up 'itself' at the same time — so I can be able to trigger many functions before each one gets completed?
import sys, os
from tkinter import *
import tkinter as tk
root = Tk()
def Sample_Function():
root.destroy()
sys.path.insert(0,'C:/Data')
import other_python_file
os.system('python this_tk_popup.py')
tk.Button(text='Run Sample_Function', command=Sample_Function).pack(fill=tk.X)
tk.mainloop()
I think this will do close to what you want. It uses subprocess.Popen() instead of os.system() to run the other script and rerun the pop-up which doesn't block execution while waiting for them to complete, so they can now execute concurrently.
I also added a Quit button to get out of the loop.
import subprocess
import sys
from tkinter import *
import tkinter as tk
root = Tk()
def sample_function():
command = f'"{sys.executable}" "other_python_file.py"'
subprocess.Popen(command) # Run other script - doesn't wait for it to finish.
root.quit() # Make mainloop() return.
tk.Button(text='Run sample_function', command=sample_function).pack(fill=tk.X)
tk.Button(text='Quit', command=lambda: sys.exit(0)).pack(fill=tk.X)
tk.mainloop()
print('mainloop() returned')
print('restarting this script')
command = f'"{sys.executable}" "{__file__}"'
subprocess.Popen(command)
Related
I have a tkinter GUI, and am interested in adding a threading component to prevent my program from freezing. Here is my code:
from tkinter import *
import os
import threading
root = Tk()
root.title('Calculation Program')
root.geometry('700x525')
def param_log_export():
to_discover = disc_mode_choice.get()
def RunCalculation():
os.system('python command_center.py')
def combine_funcs(*funcs):
def combined_func(*args, **kwargs):
for f in funcs:
f(*args, **kwargs)
return combined_func
run_click_frame= Canvas(root, width= 450, height= 525)
save_button = Button(run_click_frame, width=450,height=1,text='Run Analysis!',fg='white',relief='flat',borderwidth=5,
bg='#2F4FAA',font=(Font_tuple,15),command = threading.Thread(target=combine_funcs(param_log_export,RunCalculation)).start())
save_button.pack(side=BOTTOM)
root.mainloop()
Essentially when the button is clicked, another script is called, and that script calls all of the smaller scripts for a certain calculation:
from target_list_create import mh_table
from ion_list_format import ion_mod_full
from theo_list_generation import theo_list_record
from precursor_fragment_matching import precursor_matches
Previously, I was just using command=combine_functs(param_log_export,RunCalculation), which worked fine, other than beginning to freeze as the size of my calculations grows. So, now I am trying the threading approach using the above code, but before I even have the opportunity to click the button which would command the threaded script, the program is running as though the button was clicked immediately. The console returns: UnboundLocalError: local variable 'fdr_algorithm_report' referenced before assignment, which indicates that there is a leak and the program triggers the combine_functs function as soon as the GUI is executed.
If anyone could help me understand what the issue is, so that when I click the button it executes the command without freezing the program, I would be very appreciative.
I've read some post on stack overflow,Issues intercepting subprocess output in real time, Redirect command line results to a tkinter GUI, i know i have to use threading and queue in tkinter, but I am still can't do the same thing because I am a beginner in program,please help.
The goal: When press a button, getting the 'top' command output and realtime display in tkinter text widget
The issue: I've tried to follow the code, but still cannot get the output, but I have not idea how to make it work.
from tkinter import *
import tkinter as tk
import subprocess
from threading import Thread
from queue import Queue
window = tk.Tk()
window.title('realtime')
window.geometry('800x400')
text = tk.Text(window)
text.pack()
button = tk.Button(window, text= 'Press')
button.pack()
window.mainloop()
This is only the gui outlook, please help
top refreshes itself now and then and I'm guessing that's the behavior you want to capture with threading and whatnot. However in this case it would be much easier to ask top to only run once, and have tkinter do the timing and refreshing:
import tkinter as tk
from sh import top
def update_text():
text.delete(0.0, tk.END)
text.insert(0.0, top('-b', n=1))
window.after(1000, update_text) # call this function again in 1 second
window = tk.Tk()
window.title('realtime')
window.geometry('800x400')
text = tk.Text(window)
text.pack()
button = tk.Button(window, text= 'Press', command=update_text)
button.pack()
window.mainloop()
You may need to install sh to run top like I did, or use subprocess.check_output if you want.
text.insert(0.0, subprocess.check_output(['top', '-b', '-n 1']))
I'm using jupyter notebook on mac, recently I need to write interactive dialog box, so after google, I use Tkinter to make an interactive window.
But I was bothered by this problem couples day ,and still can't find a solution way.
Fisrt example:
from Tkinter import *
from tkFileDialog import askopenfilename
import sys
import os,time
def callback():
name= askopenfilename()
print name
errmsg = 'Error!'
Button(text='File Open', command=callback).pack(fill=X)
mainloop()
Second example:
from Tkinter import *
import sys,os
class YourApp(Tk):
def quit_and_close(self):
app.quit()
#os._exit(0)
#sys.exit(1)
#exit(0)
app = YourApp()
app.title('example')
app.geometry('400x300+200+200')
b = Button(app, text = "quit", command = app.quit_and_close)
b.pack()
app.mainloop()
And the third one:
import Tkinter as tk
import tkMessageBox
def ask_quit():
if tkMessageBox.askokcancel("Quit", "You want to quit now? *sniff*"):
root.destroy()
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", ask_quit)
root.mainloop()
After running those above code, always need have to force quit python launcher.
It is very weird, and annoying because after forcing quit, I will got the error:
Is it necessary to use python launcher as default window?
Is there possible to set another window to open ?
or is there proper way to close the launcher without causing programming crash?
p.s Even I try to use wxpython, it still open python launcher and got the same problem.
I've a GUI which will perform some functions when the buttons are pressed.
now i want to create a button in the GUI which will call and run a shell script in the background.
how can i achieve this ?
Not sure if your question is about how to call a shell script in Python, or how to make a button in your GUI. If the former, my comment above (recommending some research on subprocess.Popen) is the solution. Otherwise:
# assuming Python3
import tkinter as tk
import subprocess as sub
WINDOW_SIZE = "600x400"
root = tk.Tk()
root.geometry(WINDOW_SIZE)
tk.Button(root, text="Push me!", command=lambda: sub.call('path/to/script')).pack()
Python can run shell scripts using the supbprocess module. In order to run it in the background you can start it from a new thread.
To use the module
import subprocess
...
subprocess.call(['./yourScript.sh'])
For a good python threading resource you can try: How to use threading in Python?
Adding to what #lakesh said, below is the complete script :
import Tkinter
import subprocess
top = Tkinter.Tk()
def helloCallBack():
print "Below is the output from the shell script in terminal"
subprocess.call('./yourscript.sh', shell=True)
B = Tkinter.Button(top, text ="Hello", command = helloCallBack)
B.pack()
top.mainloop()
Please note that the shell script is in the same directory as that of the python script.
If needed, do chmod 777 yourscript.sh
subprocess.call('./yourscript.sh', shell=True)
and import Tkinter and not import tkinter solved the problems I was facing.
Use Tkinter to create a button. For more info, look at this video:http://www.youtube.com/watch?v=Qr60hWFyKHc
Example:
from Tkinter import *
root = Tk()
app = Frame(root)
app.grid()
button1 = Button(app,"Shell Script")
button1.grid()
root.mainloop()
To add the functionality:
change button1 line to:
button1 = Button(app,"Shell Script",command=runShellScript)
def runShellScript():
import subprocess
subprocess.call(['./yourScript.sh'])
I want the method tryme to run only when I push the "snackPlay" button in the gui, but it runs as soon as I run the script. What can I do to make tryme run only on command?
Thanks.
import threading
from Tkinter import *
from tkSnack import *
class MyThread ( threading.Thread ):
def tryme ( self ):
print 'up uP UP'
root = Tk()
initializeSnack(root)
f = Frame(root)
f.pack()
Button(f, bitmap='snackPlay', command=MyThread().tryme()).pack(side='left')
root.mainloop()
I don't know a lot about threading, but you should try command = MyThread().tryme instead of command = MyThread().tryme() (it works for me after I remove all the tkSnack stuff).
Tkinter callbacks expect callable objects, not function results.