Tkinter不确定进度条未按预期运行



这是一个简单的gui。我正在从条目中的用户那里获取url。按下按钮时,url将保存在一个文件中,并调用另一个函数以通过调用(在子流程内(启动另一个流程。当进程运行时,我想显示不确定的进度条(直到按下按钮,该条需要隐藏(,当进程完成时,会显示一条showinfo消息来销毁gui。

问题:直到流程结束,酒吧才会出现。显示showinfo对话框后,它才开始进行。也就是说,酒吧在真正应该被摧毁的那一刻就开始了
我的代码出了什么问题?

import scrapy
import tkinter as tk
from tkinter import messagebox as tkms
from tkinter import ttk
import shlex
from subprocess import call

def get_url():
# get value from entry and write to a file

def scrape():
progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode='indeterminate')
progress_bar.grid(row=3, column=2)
progress_bar.start(10)
command_line = shlex.split('scrapy runspider /media/mayank/Local/Coding/Lab/Scraping/Practices/img.py')
call(command_line)

mes = tkms.showinfo(title='progress', message='Scraping Done')
if mes == 'ok':
root.destroy()
root = tk.Tk()
root.title("Title")

entry1 = tk.Entry(root, width=90, textvariable=url)
entry1.grid(row=0, column=0, columnspan=3)
my_button = tk.Button(root, text="Process", command=lambda: [get_url(), scrape()])
my_button.grid(row=2, column=2)
root.mainloop()

----更新代码---

import scrapy
import tkinter as tk
from tkinter import messagebox as tkms
from tkinter import ttk
import shlex
from subprocess import call


def get_url():
# get value from entry and write to a file
scrapy = None

def watch():
global scrapy
if scrapy:
if scrapy.poll() != None:
# Update your progressbar to finished.
progress_bar.stop()
progress_bar.destroy()
# Maybe report scrapy.returncode?
print(f'scrapy return code =--######==== {scrapy.returncode}')
scrapy = None
else:
# indicate that process is running.
progress_bar.start(10)
print(f'scrapy return code =--######==== {scrapy.returncode}')
# Re-schedule `watch` to be called again after 0.1 s.
root.after(100, watch)

def scrape():
global scrapy
command_line = shlex.split('scrapy runspider ./img.py')
scrapy = Popen(command_line)
watch()
mes = tkms.showinfo(title='progress', message='Scraping Done')
if mes == 'ok':
root.destroy()

root = tk.Tk()
root.title("Title")
url = tk.StringVar(root)
entry1 = tk.Entry(root, width=90, textvariable=url)
entry1.grid(row=0, column=0, columnspan=3)
my_button = tk.Button(root, text="Process", command=lambda: [get_url(), scrape()])
my_button.grid(row=2, column=2)
progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode='indeterminate')
progress_bar.grid(row=3, column=2)
root.mainloop()

使用subprocess.call中断当前进程,直到调用的进程完成。因此,GUI在调用完成之前不会更新。

重要提示: 切勿从tkinter程序的主线程调用subprocess.runsubprocess.call或其他方便函数之一。这样做将冻结GUI。您应该只从主线程创建subprocess.Popen对象

相反,您应该创建一个Popen对象,同时禁用启动按钮。

要跟踪进度,请定义一个用root.after()周期性调用的函数,比如每0.1秒调用一次。在这个函数中,您可以调用poll()方法来检查子流程是否已经完成。或者,您可以设置stdout=subprocess.PIPE,并从Popen对象的stdout属性读取子流程中的数据。

下面的代码是基于您更新的问题的工作(对我来说(示例。请注意,我已经在UNIX机器上用一个相对长时间运行的命令替换了scrapy(我没有(。由于您正在将scrapy作为子流程运行,因此不需要import scrapy

import tkinter as tk
from tkinter import messagebox as tkms
from tkinter import ttk
from subprocess import Popen

proc = None

def watch():
global proc
if proc:
if proc.poll() is not None:
# Update your progressbar to finished.
progress_bar.stop()
progress_bar.destroy()
# Maybe report proc.returncode?
print(f'proc return code =--######==== {proc.returncode}')
proc = None
mes = tkms.showinfo(title='progress', message='Scraping Done')
if mes == 'ok':
root.destroy()
else:
# indicate that process is running.
progress_bar.start(10)
# print(f'proc return code =--######==== {proc.returncode}')
# Re-schedule `watch` to be called again after 0.1 s.
root.after(100, watch)

def scrape():
global proc
command_line = ['netstat']
proc = Popen(command_line)
watch()

root = tk.Tk()
root.title("Title")
url = tk.StringVar(root)
entry1 = tk.Entry(root, width=90, textvariable=url)
entry1.grid(row=0, column=0, columnspan=3)
my_button = tk.Button(root, text="Process", command=lambda: [get_url(), scrape()])
my_button.grid(row=2, column=2)
progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode='indeterminate')
progress_bar.grid(row=3, column=2)
root.mainloop()

相关内容

最新更新