使用 tkinter 为单独的程序编写 Python UI。该程序的停止按钮基本上冻结 UI 并继续执行脚本

Writing a Python UI for a seperate program with tkinter. The stop button for this program basically freezes the UI and continues with the script

这是我编写的代码...

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()

我正在寻找一种方法让我的程序停止另一个按钮运行的程序。我意识到这可能是一个“自毁按钮”,但我不知道如何使用另一个按钮运行的脚本来做到这一点。非常感谢任何帮助!我尝试通过将 def ex_activation 放在 p.kill 中来终止代码 这没有用...

如果另一个 python 脚本永远设为 运行(有某种 while True:),您不能在命令行上 运行 它,因为你做到了,因为它会在该脚本 运行ning.

时冻结你的 window

为了在后台 运行 一个 python 脚本,您需要使用子进程库来完成。 (找出来)

我还找到了另一个 的答案,它使用 check_ouput() 来了解 python 程序何时完成。如果您想向 tkinter 应用程序发送状态,这也很有用:例如,您可以 print("33% Complete")。您可以将它添加到 tkinter 的主循环中,这样您就可以始终知道您的程序是否 运行ning。

最后但同样重要的是,要终止该进程(使用停止按钮),您应该使用 os 并查找子进程的 ID。 Here你也可以找到一个很好的例子。

我会尝试这样的事情:

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()

编辑

使用问题代码的示例代码。警告:我已经更改了用于测试的 png 文件位置,评论了应用程序图标,并且仅在 Windows.

上进行了测试

重要的是删除主文件上的 mainloop() 并放置 update...() 以捕获(我不知道为什么)正在杀死父进程和子进程的键盘中断。

我邀请你尝试一下,在测试了半小时后,就像我在工作时一样快乐!!

文件 1:daemon.py - 此文件将永远 运行。

from time import sleep
from sys import exit

while True:
    try:
        print("hello")
        sleep(1)
    except KeyboardInterrupt:
        print("bye")
        exit()

文件 2:tkinterapp.py - 名称是 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