this is my first time here so if I break some unwritten rules please don't shoot me
I've been trying build an app for editing, reading and opening .ahk files. The last one gives me problems.
this code kind of does what I want except it fires the command immediately after opening the app.
from tkinter import *
from tkinter import filedialog
import os
import threading
root = Tk()
def openfile():
os.system( r'\Users\merijn\PycharmProjects\infoprojectP3\venv\Scripts\ahkScript1.ahk')
def func():
print("hello")
btn1 = Button(text='programma', command=threading.Thread(target=openfile).start())
btn2 = Button(text='ander ding', command=func)
btn1.pack()
btn2.pack()
root.mainloop()
Any help would be much appreciated!
Change the following line (it just assigns the result of threading.Thread(...) to command option):
Button(text="run program1", command=threading.Thread(target=lambda: os.system(r'\Users\merijn\PycharmProjects\infoprojectP3\venv\Scripts\ahkScript1.ahk').start()))
to
Button(text="run program1", command=lambda: threading.Thread(target=lambda: os.system(r'\Users\merijn\PycharmProjects\infoprojectP3\venv\Scripts\ahkScript1.ahk')).start())
or
Button(text="run program1", command=lambda: threading.Thread(target=os.system, args=[r'\Users\merijn\PycharmProjects\infoprojectP3\venv\Scripts\ahkScript1.ahk']).start())
Same for buttons of run program2 and run program3.
Update: based on your updated code, you need to change the following line:
btn1 = Button(text='programma', command=threading.Thread(target=openfile).start())
to
btn1 = Button(text='programma', command=lambda: threading.Thread(target=openfile).start())
Related
Tkinter is adding newlines every 30 seconds:
Unwanted newlines
I'm running this in windows CMD.
I wrote a simple program to test this with a single askopenfilename() call in there.
When I click the browse button, it adds a newline, then after I choose the file and click begin, it adds a newline every 30 seconds while the program is "running":
import tkinter as tk
from tkinter import filedialog
from tkinter.filedialog import askdirectory
import time
def input1():
input1_path = tk.filedialog.askopenfilename()
input1_entry.delete(1, tk.END) # Remove current text in entry
input1_entry.insert(0, input1_path) # Insert the 'path'
#returns file paths for the input files and output directory
def begin():
global inputFileName
inputFileName = input1_entry.get()
master.destroy()
master = tk.Tk()
master.title('Omega NExT Archive Plotter')
one_frame = tk.Frame(master)
two_frame = tk.Frame(master)
line1 = tk.Frame(master, height=1, width=400, bg="grey80", relief='groove')
input1_path = tk.Label(one_frame, text="Archive File Input:")
input1_entry = tk.Entry(one_frame, text="", width=60)
browse1 = tk.Button(one_frame, text="Browse", command=input1)
begin_button = tk.Button(two_frame, text='Begin!', command=begin)
one_frame.pack(side=tk.TOP)
line1.pack(pady=10)
two_frame.pack(side=tk.BOTTOM)
input1_path.pack()
input1_entry.pack()
browse1.pack(pady=10)
begin_button.pack(pady=20, fill=tk.X)
master.mainloop()
time.sleep(1000000)
So I have other guys I work with running this on their computers, and it sounds like the problem is happening on our "managed" computers, but not the "less-than-managed" computers. It sounds like some kind of weird IT issue.
I have a test.exe written in Python and I want to call it from this location C:\Folder. I know calling .py is possible like the code below:
Code:
import sys
import os
from tkinter import *
window=Tk()
window.title("Running Python Script")
window.geometry('550x200')
def run():
os.system('opencv_video.py')
btn = Button(window, text="Click Me", bg="black", fg="white",command=run)
btn.grid(column=0, row=0)
window.mainloop()
Is there a similar code that calls the test.exe that I have? Any suggestion will be highly appreciated. Thank you very much
So I'm trying to use a Tkinter window as an output log. My main program is a command line interface, so if the output from the "side programs" that run fills up the python console, it can ruin the user experience.
I have the Tkinter output log program in a seperate file, which I import into my main file. This is the gyst of the Tkinter file I created:
import time
from datetime import datetime
root = Tk()
root.configure(background='black')
root.geometry('700x460')
console = Listbox(root, width=40000, height=30000, font=('Lucida Console', 14), relief=FLAT, bg='black',
fg='white',
borderwidth=0, highlightbackground='black', selectbackground='black',
selectforeground='white')
console.pack()
def log(what_to_log):
now = datetime.now()
console.insert('[' + now.strftime("%H:%M:%S") + ']: ' + what_to_log)
root.mainloop()
So I import it into my main program like so:
# this is the file with the Tkinter code
import Logs
Logs.log('Test')
The issue is that the main program doesn't continue running after importing Logs, it just stops, and continues to run the mainloop in the Logs file.
So my question is, how could I get both files to continue running, while also being able to update the Tkinter listbox via the log function??
You should not execute root.mainloop() as it will block your console application. Use root.update() at the end of log() to force tkinter to update the list box. Also there is syntax error in console.log(...).
Below is a modified Logs.py:
from tkinter import *
from datetime import datetime
root = Tk()
root.configure(background='black')
root.geometry('700x460')
console = Listbox(root, font=('Lucida Console', 14), relief=FLAT, bg='black', fg='white',
borderwidth=0, highlightbackground='black', selectbackground='black',
selectforeground='white')
console.pack(fill='both', expand=1)
def log(what_to_log):
now = datetime.now()
console.insert('end', '['+now.strftime("%H:%M:%S")+']: '+what_to_log)
console.see('end') # make sure last log is visible
root.update() # force tkinter to update
Here is what I coded...
import tkinter as tk
import subprocess
import sys
import time
import os
import tkinter.font as font
from tkinter.ttk import *
app = tk.Tk()
app.geometry("400x400")
app.configure(bg='gray')
photo = tk.PhotoImage(file=r"C:\Users\ex\ex_button_active.png")
myFont = font.Font(family='Helvetica', size=20, weight='normal')
tk.Label(app, text='EX', bg='gray', font=(
'Verdana', 15)).pack(side=tk.TOP, pady=10)
app.iconbitmap(r'C:\Users\ex\ex_icon.ico')
start = time.time()
cmd = sys.executable + " -c 'import time; time.sleep(2)' &"
subprocess.check_call(cmd, shell=True)
assert (time.time() - start) < 1
p = subprocess.Popen(cmd, shell=True)
def ex_activation():
#Python Code
#Python Code...
def ex_stop():
sys.exit(ex_activation) #This area is basically where I have a button to terminate the other script running.
#I have tried sys.exit() and had the same result
ex_activation_button = tk.Button(app,
bg='black',
image=photo,
width=120,
height=120,
command=ex_activation)
ex_stop_button = tk.Button(app,
bg='Gray',
text='ex',
width=12,
command=ex_stop
height=3)
ex_stop_button['font'] = myFont
app.title("Example")
ex_activation_button.pack(side=tk.TOP)
ex_stop_button.pack(side=tk.LEFT)
app.mainloop()
I am looking for a way to get my program to stop the program the other button runs. I realized that this maybe be a "self destruct button" but I don't know how to do this with the script the other button runs. Any help greatly appreciated! I tried killing the code by putting the def ex_activation in the p.kill
This did not work...
If the other python script is made to run forever (has some kind of while True:), you can't run it on the command line as you did, because it will freeze your window while that script is running.
In order to run a python script on background you will need to do it with the subprocess library. (Find out here)
I also found an answer of another question that uses check_ouput() in order to know when the python program has finished. This can also be useful if you want to send a status to the tkinter app: you can print("33% Complete"), for example. You could add this in tkinter's main loop, so you always know if your program is running or not.
And last but not least, to kill that process (using the stop button), you should do it using os, and looking for the subprocess' ID. Here you can also find a good example.
I would try something like this:
cmd = "exec python file.py"
p = subprocess.Popen(cmd, shell=True)
# Continue running tkinter tasks.
tk.update()
tk.update_idletasks() # These both lines should be inside a while True
# Stop secondary program
p.kill()
EDIT
Example code using your question's code. WARNING: I have changed the png file location for testing, commented the app icon, and tested ONLY on Windows.
It's important to remove the mainloop() on the main file and put update...() in order to catch the keyboardInterrupt that (I don't know why) is killing both parent and child process.
I invite you to try it and be as happy as I have been when it was working after half an hour of testing!!
File 1: daemon.py - this file will run forever.
from time import sleep
from sys import exit
while True:
try:
print("hello")
sleep(1)
except KeyboardInterrupt:
print("bye")
exit()
File 2: tkinterapp.py - The name is self-explainatory
import tkinter as tk
import subprocess
import sys
import time
import os
import tkinter.font as font
from tkinter.ttk import *
app = tk.Tk()
app.geometry("400x400")
app.configure(bg='gray')
photo = tk.PhotoImage(file=r"C:\Users\royal\github\RandomSketches\baixa.png")
myFont = font.Font(family='Helvetica', size=20, weight='normal')
tk.Label(app, text='EX', bg='gray', font=(
'Verdana', 15)).pack(side=tk.TOP, pady=10)
# app.iconbitmap(r'C:\Users\ex\ex_icon.ico')
def ex_activation():
global pro
print("running!")
pro = subprocess.Popen("python daemon.py", shell=True)
def ex_stop():
global pro
print("stopping!")
os.kill(pro.pid, 0)
ex_activation_button = tk.Button(app,
bg='black',
image=photo,
width=120,
height=120,
command=ex_activation)
ex_stop_button = tk.Button(app,
bg='Gray',
text='ex',
width=12,
command=ex_stop, # BE CAREFUL You were missing a "," here !!!
height=3)
ex_stop_button['font'] = myFont
app.title("Example")
ex_activation_button.pack(side=tk.TOP)
ex_stop_button.pack(side=tk.LEFT)
# app.mainloop()
while True:
try:
app.update()
app.update_idletasks()
except KeyboardInterrupt:
pass
I've made a GUI with Tkinter and i linked a script to a button. I've also created a browse file option in my GUI and when i select a file i store it's path into a variable named "file". What i'm trying to do is click the button and run the script using the path i stored into the variable "file", but i get a 'no such file or directory error'. The solution must be pretty obvious but i just can't figure it out. Here's my GUI code:
from tkinter import *
from tkinter import filedialog
from tkinter import ttk
from tkinter import messagebox
import subprocess
window = Tk()
#modify window
window.title("Random Title")
window.geometry("600x400")
tab_control = ttk.Notebook(window)
#Creating tabs
tab1 = ttk.Frame(tab_control)
tab2 = ttk.Frame(tab_control)
#Modifying tabs
tab_control.add(tab1, text='Issue')
tab_control.add(tab2, text='Verify')
file = ""
var = StringVar()
var.set("")
w = Entry(tab2,textvariable=var)
w.grid(column=1,row=0)
#Creating button & actions
def issue():
subprocess.call('./issue_script.sh', shell=True)
messagebox.showinfo('Issue Certificate', 'Certificate issued successfully!')
btn = Button(tab1, text="Issue Certificate", command=issue)
btn.grid(column=1, row=5)
def browse():
file = filedialog.askopenfilename(filetypes = (("all files","*.*"),("Text files","*.txt")))
var.set(file)
print(file)
btn2 = Button(tab2, text="Browse", command=browse)
btn2.grid(column=3, row=0)
def verify():
subprocess.call(['./verify_script.sh', file], shell=True)
btn = Button(tab2, text="Verify Certificate", command=verify)
btn.grid(column=1, row=5)
tab_control.pack(expand=1, fill='both')
#event loop
window.mainloop()
I've also added a print(file) command so that i see what is stored in the variable and i get the correct result(the path i selected). Maybe the error is in the line i call the script subprocess.call(['./verify_script.sh', file], shell=True) or in the script itself. Here's the script code:
#!/bin/bash
echo "Verifying certificate..."
cd
python3 cert-issuer/cert-verifier/cert_verifier/verifier.py $1
I actually made it work, but i don't know why it does.
All i changed was instead of calling my script like this
subprocess.call(['./verify_script.sh', var.get()], shell=True)
i omitted the shell=True command and the argument passes correctly into the script.
So i called subprocess.call(['./verify_script.sh', var.get()]) and it works just fine but i can't think why. Any explanation is much appreciated.