使用 tkinter 和多处理可执行创建多个窗口
Posted
技术标签:
【中文标题】使用 tkinter 和多处理可执行创建多个窗口【英文标题】:Executable using tkinter and multiprocessing creates multiple windows 【发布时间】:2016-07-19 17:12:41 【问题描述】:我已经使用 tkinter 为脚本构建了一个 gui。
我尝试使用 cx_freeze 和 pyinstaller 构建可执行文件。
我广泛使用 scipy、numpy、statsmodels 和 matplotlib
每当我单击“运行”按钮时,它都会生成另一个窗口,并且它下面的窗口停止响应。这似乎可以无限期地发生。
我确实在我的应用程序中使用了多处理,但我在 python 脚本版本中修复了多窗口问题
如何解决我的独立程序中的多窗口问题?
如果没有合理的修复,有没有其他方法可以打包程序使用?也许是自定义 Python 发行版?
from tkinter import *
from tkinter import ttk
def run():
import multiprocessing
import risers_fallers
import time
time_periods = list()
time_periods.append(month.get())
time_periods.append(threemonth.get())
time_periods.append(sixmonth.get())
time_periods.append(year.get())
#print(infile.get(), time_periods, filter_val.get(), outfile.get())
#loading screen
toplevel = Toplevel()
toplevel.focus_force()
loading = Label(toplevel, text = "RUNNING")#PhotoImage(file= photopath, format="gif - ")
loading.pack()
subproc = multiprocessing.Process(target = risers_fallers.risers_fallers, args = (infile.get(), time_periods, filter_val.get(), outfile.get(),
top_x.get(), excel.get(), tableau.get(), onecat.get(), multicat.get(), external.get()))
subproc.start()
subproc.join()
toplevel.destroy()
def browsecsv():
from tkinter import filedialog
Tk().withdraw()
filename = filedialog.askopenfilename()
#print(filename)
infile.set(filename)
if __name__ == "__main__":
#initialize tk
root = Tk()
#set title
root.title("FM Risers and Fallers")
#create padding, new frame, configure columns and rows
#mainframe = ttk.Frame(root, padding="3 3 12 12")
#our variables
month = BooleanVar()
threemonth = BooleanVar()
sixmonth = BooleanVar()
year = BooleanVar()
excel = BooleanVar()
tableau = BooleanVar()
onecat = BooleanVar()
multicat = BooleanVar()
external = BooleanVar()
top_x = StringVar()
top_x.set("15")
infile = StringVar()
outfile = StringVar()
filter_val = StringVar()
photopath = "./41.gif"
#default values
filter_val.set("30")
import datetime
from re import sub
d = datetime.datetime.now()
outfile.set(sub('[^0-9|\s]',' ', str(d)))
"""
our widgets
"""
#labels for tab 1 Not needed with pane view
# ttk.Label(mainframe, text="Input file") #.grid(column=3, row=1, sticky=W)
# ttk.Label(mainframe, text="Output name") #.grid(column=3, row=1, sticky=W)
# ttk.Label(mainframe, text="Dashboard period of times") #.grid(column=3, row=1, sticky=W)
# ttk.Label(mainframe, text="Filter by growth rate") #.grid(column=3, row=1, sticky=W)
master = Frame(root, name = 'master')
master.pack(fill=BOTH)
#notebook container
notebook = ttk.Notebook(master)
notebook.pack(fill=BOTH, padx=2, pady=3)
tab0 = ttk.Frame(notebook)
tab1 = ttk.Frame(notebook)
tab2 = ttk.Frame(notebook)
notebook.add(tab0, text='Risers and Fallers')
notebook.add(tab1, text='Help')
notebook.add(tab2, text='About')
#tab 1 panes
panel_0 = ttk.Panedwindow(tab0, orient=VERTICAL)
file_pane_0 = ttk.Labelframe(panel_0, text='Input and Output', width = 300, height=100)
dashboard_pane_0 = ttk.Labelframe(panel_0, text='Dashboard Time Period', width = 300, height=200)
filter_pane_0 = ttk.Labelframe(panel_0, text='Filter by Growth Rate', width = 300, height=200)
run_frame_0 = Frame(panel_0, width = 300, height=100)
output_options_frame = ttk.Labelframe(panel_0, text='Output Options', width = 300, height=200)
top_x_frame_0 = ttk.Labelframe(panel_0, text = "Number of Risers", width = 300, height=100)
#grid it
panel_0.pack(fill=BOTH, expand=1)
file_pane_0.grid(row = 0, column = 0, columnspan = 3)
dashboard_pane_0.grid(row = 1, column = 0)
filter_pane_0.grid(row = 2, column = 0)
output_options_frame.grid(row = 1, column = 1)
top_x_frame_0.grid(row = 2, column = 1)
#pack em!
# panel_0.pack(fill=BOTH, expand=1)
# file_pane_0.pack(fill=X, expand=1)
# dashboard_pane_0.pack(side = LEFT, fill = Y)
# filter_pane_0.pack(side = RIGHT, fill = Y)
# top_x_frame_0.pack(fill=BOTH, expand=1)
#tab 2 panes
panel_1 = ttk.Panedwindow(tab1, orient=VERTICAL)
file_pane_1 = ttk.Labelframe(panel_1, text='Input and Output', width = 300, height=100)
dashboard_pane_1 = ttk.Labelframe(panel_1, text='Dashboard Time Period', width = 300, height=300)
filter_pane_1 = ttk.Labelframe(panel_1, text='Filter by Growth Rate', width = 300, height=300)
#pack em!
panel_1.pack(fill=BOTH, expand=1)
file_pane_1.pack(fill=BOTH, expand=1)
dashboard_pane_1.pack(side = LEFT, fill = Y)
filter_pane_1.pack(side = RIGHT, fill = Y)
#tab 3 panes
panel_2 = ttk.Panedwindow(tab2, orient=VERTICAL)
about_pane = ttk.Labelframe(panel_2, text='About', width = 300, height=200)
description_pane = ttk.Labelframe(panel_2, text='Description', width = 300, height=200)
citation_pane = ttk.Labelframe(panel_2, text='Citations', width = 300, height=200)
#pack em!
panel_2.pack(fill=BOTH, expand=1)
about_pane.pack(fill=BOTH, expand=1)
description_pane.pack(fill=BOTH, expand=1)
citation_pane.pack(fill=BOTH, expand=1)
#labels for tab 2 (help)
dashboard_help = ttk.Label(dashboard_pane_1, text= """Choose what units of
time to create a
dashboard for.
Note that time
periods are most
recent, not a
defined quarter or
calendar year.""")
io_help = ttk.Label(file_pane_1, text="""Output file: the first words to use in the naming of the output files
Input file: the BW output that you want to analyze.
See documentation for required format.""")
dashboard_help.pack()
io_help.pack(fill = BOTH)
#labels for tab 3 (about)
about_section = ttk.Label(about_pane, text="""The FM Risers and Fallers project was created by Jeremy Barnes
from May 2016 - July 2016 as a way to identify highest growing
parts.
Business logic was created based upon discussions with
Daniel DiTommasso, David Enochs, Alex Miles
and Robert Pietrowsky.
""")
description_section = ttk.Label(description_pane, text="""The FM Risers and Fallers application loads BW output from a
specific format, performs seasonal adjustment on the data,
derives information from the dataand then outputs all
derived information and dashboards with ranking information.
""")
citations_section = ttk.Label(citation_pane, text="""The FM Risers and Fallers project was created using
x13-ARIMA-SEATS by the US Census Bureau
pandas
statsmodels
Download links are available in the documentation
""")
#pack em
about_section.pack(fill=BOTH, expand=1)
description_section.pack(fill=BOTH, expand=1)
citations_section.pack(fill=BOTH, expand=1)
#file entry
#output
#output = Frame(file_pane_0, width = 300, height=50)
output_label = ttk.Label(file_pane_0, text="Output file").grid(column=1, row=1, sticky=W)
outfile_entry = ttk.Entry(file_pane_0, width = 50, textvariable = outfile).grid(column=2, row=1, sticky=W)
# output.pack(side = TOP, fill = X)
# output_label.pack(side = LEFT)
# outfile_entry.pack(side = RIGHT)
#input
#input = Frame(file_pane_0, width = 300, height=50)
input_label = ttk.Label(file_pane_0, text="Input file").grid(column=1, row=2, sticky=W)
infile_entry = ttk.Entry(file_pane_0, width = 50, textvariable = infile).grid(column=2, row=2, sticky=W)
#cbutton.grid(row=10, column=3, sticky = W + E)
bbutton= Button(file_pane_0, text="Browse", command= browsecsv).grid(column = 3, row = 2)
# input.pack(side = BOTTOM, fill = X)
# input_label.pack(side = LEFT)
# infile_entry.pack(side = RIGHT)
#top_x
top_x_label = ttk.Label(top_x_frame_0, text="Risers/Fallers to identify").grid(column=1, row=2, sticky=W)
top_x_entry = ttk.Entry(top_x_frame_0, width = 7, textvariable = top_x).grid(column=2, row=2, sticky=W)
#dashboard times
monthly = Checkbutton(dashboard_pane_0, text = "Month", variable = month).grid(row = 1, sticky=W, pady=1)
threemonthly = Checkbutton(dashboard_pane_0, text = "3 Months", variable = threemonth).grid(row = 2, sticky=W, pady=1)
sixmonthly = Checkbutton(dashboard_pane_0, text = "6 Months", variable = sixmonth).grid(row = 3, sticky=W, pady=1)
yearly = Checkbutton(dashboard_pane_0, text = "Year", variable = year).grid(row = 4, sticky=W, pady=1)
#output options
excel_button = Checkbutton(output_options_frame, text = "Excel", variable = excel).grid(row = 1, sticky=W, pady=1)
tableau_button = Checkbutton(output_options_frame, text = "Tableau", variable = tableau).grid(row = 2, sticky=W, pady=1)
onecat_button = Checkbutton(output_options_frame, text = "One Category", variable = onecat).grid(row = 3, sticky=W, pady=1)
multicat_button = Checkbutton(output_options_frame, text = "Many Categories", variable = multicat).grid(row = 4, sticky=W, pady=1)
external_button = Checkbutton(output_options_frame, text = "External Report", variable = external).grid(row = 5, sticky=W, pady=1)
#growth rate stuff
growth_input_label = ttk.Label(filter_pane_0, text="Analyze only top: ").grid(row = 1, column = 1, sticky=W, pady = 4, padx = 4)
growth_input = ttk.Entry(filter_pane_0, width = 7, textvariable = filter_val).grid(row = 1, column = 2, sticky=W, pady = 4, padx = 4)
# Radiobutton(filter_pane_0, text = "Standard Deviations", variable = stddev, value = 1).grid(row = 2, column = 1, sticky=W, pady = 4)
# Radiobutton(filter_pane_0, text = "Percentage", variable = stddev, value = 0).grid(row = 2, column = 2, sticky=W, pady = 4)
#growth_default_label = ttk.Label(filter_pane_0, text="(Leave blank for default").grid(row = 3, column = 1, sticky=W, pady = 4, padx = 4)
percent_label = ttk.Label(filter_pane_0, text=" %").grid(row = 1, column = 3, sticky=W, pady = 4, padx = 4)
#launch button
run_buttom_frame = Frame(panel_0, width = 300, height=50)
run_button = Button(run_buttom_frame, text = "RUN ANALYSIS", command = run)
run_button.pack()
run_buttom_frame.grid(row = 3, column = 0, columnspan = 2, pady = 4)
root.mainloop()
【问题讨论】:
你的 sn-p 呢??? 请仔细阅读:***.com/help/how-to-ask 你的脚本中是否有if __name__ == '__main__'
(包含传递给Process(target=...)
的函数的那个?
是的,我包括 if name == 'main'
【参考方案1】:
两个或更多进程不能共享一个根窗口。每个创建小部件的进程都会有自己的窗口。
【讨论】:
【参考方案2】:我通过一些实验设法解决了这个问题。
我在同一个进程中启动业务逻辑后,它不再启动多个窗口。
【讨论】:
您能否分享您为解决上述问题所做的更改,因为我也面临同样的问题。以上是关于使用 tkinter 和多处理可执行创建多个窗口的主要内容,如果未能解决你的问题,请参考以下文章