如何制作python模块';s、 py函数与带有Tkinter的main.py变量交互?
我的目标是在main.py文本小部件中显示函数的输出。 如何使循环函数将其数据输出到main.py文件中的文本框? **更新2** **原创的 应用程序的Gui: Gui的主要代码:如何制作python模块';s、 py函数与带有Tkinter的main.py变量交互?,python,function,variables,tkinter,module,Python,Function,Variables,Tkinter,Module,我的目标是在main.py文本小部件中显示函数的输出。 如何使循环函数将其数据输出到main.py文件中的文本框? **更新2** **原创的 应用程序的Gui: Gui的主要代码: import tkinter as tk import multiprocessing as mp import os import testping import sys class GUI(tk.Tk): def __init__(self, *args, **kwargs):
import tkinter as tk
import multiprocessing as mp
import os
import testping
import sys
class GUI(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.geometry("860x600")
self.title("GUI Project")
menu = tk.Frame(self, relief="solid")
container = tk.Frame(self, relief="solid")
menu.pack(side="left", fill="y")
container.pack(side="right", fill="y", expand=True)
menu.grid_rowconfigure(0, weight=1)
container.grid_rowconfigure(0, weight=1)
container.grid_rowconfigure(1, weight=1)
container.grid_rowconfigure(2, weight=1)
container.grid_rowconfigure(3, weight=1)
container.grid_rowconfigure(4, weight=1)
container.grid_rowconfigure(5, weight=1)
container.grid_rowconfigure(6, weight=1)
container.grid_columnconfigure(0, weight=1)
container.grid_columnconfigure(1, weight=2)
container.grid_columnconfigure(2, weight=2)
container.grid_columnconfigure(3, weight=2)
container.grid_columnconfigure(4, weight=2)
container.grid_columnconfigure(5, weight=2)
container.grid_columnconfigure(6, weight=2)
self.frames = ["Menu", "TestPing", "FutureFeature", "FutureFeature2", "FutureFeature3"]
self.frames[0] = Menu(parent=menu, controller=self)
self.frames[1] = TestPing(parent=container, controller=self)
self.frames[2] = FutureFeature(parent=container, controller=self)
self.frames[3] = FutureFeature2(parent=container, controller=self)
self.frames[4] = FutureFeature3(parent=container, controller=self)
self.frames[0].grid(row=0, column=0, sticky="nsew")
self.frames[1].grid(row=0, column=0, sticky="nsew")
self.frames[2].grid(row=0, column=0, sticky="nsew")
self.frames[3].grid(row=0, column=0, sticky="nsew")
self.frames[4].grid(row=0, column=0, sticky="nsew")
self.show_frame(1)
def show_frame(self, page_name):
frame = self.frames[page_name]
print(frame)
frame.tkraise()
frame.grid(row=0, column=0, sticky="nsew")
class Menu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
ping_test_button = tk.Button(self, text="Ping Test", bg="skyblue1", pady=30,
command=lambda: controller.show_frame(1))
future_feature1_button = tk.Button(self, text="FutureFeature", bg="dark violet", pady=30,
command=lambda: controller.show_frame(2))
future_feature2_button = tk.Button(self, text="FutureFeature2", bg="pale goldenrod", pady=30,
command=lambda: controller.show_frame(3))
future_feature3_button = tk.Button(self, text="FutureFeature3", bg="green", pady=30,
command=lambda: controller.show_frame(4))
app_exit = tk.Button(self, text="Quit", bg="gray40", pady=30,
command=lambda: self.terminate())
ping_test_button.pack(fill="both", expand=True)
future_feature1_button.pack(fill="both", expand=True)
future_feature2_button.pack(fill="both", expand=True)
future_feature3_button.pack(fill="both", expand=True)
app_exit.pack(fill="both", expand=True)
def terminate(self):
while True:
path = fr'c:/users/{os.getlogin()}/desktop/Gui-Skeleton'
try:
os.rmdir(path)
exit()
except OSError as err:
print(f"Error Deleting tmp folder! {err}")
exit()
class TestPing(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, bg="skyblue1")
self.controller = controller
self.clear_file = tk.BooleanVar()
self.clear_file.set(False)
self.url_label = tk.Label(self, text="Enter URL : ", padx=7, pady=5, bg="skyblue1")
self.url_input_box = tk.Entry(self)
self.file_name_label = tk.Label(self, text="Enter Filename: ", bg="skyblue1")
self.file_name_input_box = tk.Entry(self)
self.clear_file_label = tk.Label(self, text="Clear File?", padx=5, pady=5, bg="skyblue1")
self.clear_file_radio_yes = tk.Radiobutton(self, text="yes", value=True, var=self.clear_file, bg="skyblue1",
command=lambda: self.callback(self.clear_file.get()))
self.clear_file_radio_no = tk.Radiobutton(self, text="no", value=False, var=self.clear_file, bg="skyblue1",
command=lambda: self.callback(self.clear_file.get()))
self.submit_button = tk.Button(self, text="Submit", width=10, height=1,
command=lambda: self.condition(self.url_input_box.get(),
self.clear_file.get(),
self.file_name_input_box.get()))
self.clear_fields_button = tk.Button(self, text="Clear Fields", width=10,
command=lambda: self.clear_boxes(self.url_input_box,
self.file_name_input_box))
self.text_input = tk.StringVar()
self.text_window = tk.Text(self, height=100, width=500, bg="gray")
self.clear_window_button = tk.Button(self, text="Clear Window", width=10,
command=lambda: self.clean_window())
self.grid_columnconfigure(0, minsize=50, weight=0)
self.grid_columnconfigure(1, minsize=20, weight=2)
self.grid_columnconfigure(2, minsize=50, weight=3)
self.grid_columnconfigure(3, minsize=20, weight=2)
self.grid_rowconfigure(0, minsize=50, weight=0)
self.grid_rowconfigure(1, minsize=20, weight=0)
self.grid_rowconfigure(2, minsize=30, weight=0)
self.grid_rowconfigure(3, minsize=10, weight=0)
self.grid_rowconfigure(4, minsize=10, weight=0)
self.grid_rowconfigure(5, minsize=10, weight=0)
self.url_label.grid(row=0, column=0, sticky="w")
self.url_input_box.grid(row=0, column=1, sticky="w")
self.file_name_label.grid(row=1, column=0, sticky="w")
self.file_name_input_box.grid(row=1, column=1, sticky="w")
self.clear_file_label.grid(row=0, column=1, sticky="n")
self.clear_file_radio_yes.grid(row=1, column=1)
self.clear_file_radio_no.grid(row=2, column=1)
self.submit_button.grid(row=3, column=1, sticky="se")
self.clear_fields_button.grid(row=3, column=1, sticky="sw")
self.text_window.grid(row=7, column=1, rowspan=3, sticky="we")
self.clear_window_button.grid(row=8, column=0)
def clear_boxes(self, url_input, filename):
url_input.delete(0, "end")
filename.delete(0, "end")
def callback(self, clear):
print(f'Clear file = {clear}') # Debugging Mode - check Radio box Var.
def condition(self, host, clear, filename):
print(clear, filename) # Debugging - Input Validation
if clear is True and filename == '':
self.handler_clr_yes_fn_no(host)
elif clear is False and filename == '':
self.handler_clr_no_fn_no(host)
elif clear is True and filename != '':
self.handler_clr_yes_fn_yes(host, filenameInputBox)
elif clear is False and filename != '':
self.handler_clr_no_fn_yes(host, filenameInputBox)
def handler_clr_yes_fn_no(self, host):
startprocs = []
lastprocs = []
proc1 = mp.Process(name="Clear + No Filename + WriteFile",
target=testping.clr_yes_fn_no_writefile, args=(host,))
proc2 = mp.Process(name="Clear + No Filename + PrintOutput",
target=testping.clr_yes_fn_no_print_output, args=(host,))
proc3 = mp.Process(name="Clear + No Filename + Generate PrintOutput to GUI",
target=testping.clr_yes_fn_no_print_to_gui, args=(host,))
proc4 = mp.Process(name="Remove first line + Write new default file",
target=testping.delete_default_lines)
startprocs.append(proc1)
startprocs.append(proc2)
startprocs.append(proc3)
lastprocs.append(proc4)
for s in startprocs:
s.start()
for s2 in startprocs:
s2.join()
for l in lastprocs:
l.start()
def handler_clr_no_fn_no(self, host):
procs = []
nextprocs = []
proc1 = mp.Process(name="Append to default file",
target=testping.clr_no_fn_no_writefile, args=(host,))
proc2 = mp.Process(name="Print Output", target=testping.clr_no_fn_no_printoutput, args=(host,))
procs.append(proc1)
procs.append(proc2)
for proc in procs:
proc.start()
for proc in procs:
proc.join()
for p in nextprocs:
p.start()
def handler_clr_yes_fn_yes(self, host, filenameInputBox):
procs = []
nextprocs = []
proc1 = mp.Process(name="Clear file + userFilename + Write to file",
target=testping.clr_yes_fn_yes_writefile, args=(host, filenameInputBox,))
proc2 = mp.Process(name="Clear file + user filename + Print output",
target=testping.clr_yes_fn_yes_printoutput, args=(host,))
proc3 = mp.Process(name="Remove Empty Lines from user filename",
target=testping.delete_userfile_lines, args=(filenameInputBox,))
procs.append(proc1)
procs.append(proc2)
nextprocs.append(proc3)
for proc in procs:
proc.start()
for p in procs:
p.join()
for np in nextprocs:
np.start()
def handler_clr_no_fn_yes(self, host, filenameInputBox):
procs = []
proc1 = mp.Process(name="Keep File + Userfilename + Append to Userfile",
target=testping.clr_no_fn_yes_writefile, args=(host, filenameInputBox,))
proc2 = mp.Process(name="Keep File + Userfilename + Print Output",
target=testping.clr_no_fn_yes_printoutput, args=(host,))
procs.append(proc1)
procs.append(proc2)
for p in procs:
p.start()
for p2 in procs:
p2.join()
class FutureFeature(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, bg="mediumpurple1")
self.controller = controller # can be used to run self.controller.show_frame[]
class FutureFeature2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, bg="light goldenrod")
self.controller = controller
class FutureFeature3(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent, bg="green")
self.controller = controller
def check_path():
path = fr'c:/users/{os.getlogin()}/desktop/Gui-Skeleton'
try:
if os.path.isdir(path):
pass
else:
os.mkdir(path)
pass
except OSError as err:
print(f"[!] Operation failed! {err}")
if __name__ == "__main__":
check_path()
app = GUI()
app.mainloop()
模块testping.py的主要代码:
import subprocess as sub
import multiprocessing as mp
import time
import os
import sys
import tkinter as tk
clear_file = False
host = ""
filename = ""
text_box = tk.StringVar()
old_sys = sys.stdout
def delete_default_lines():
time.sleep(1.5)
print(f'\nCurrent Proccess: {mp.current_process().name} + {mp.current_process().pid}')
file = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/default-tmp.txt'
newfile = fr'c:/users/{os.getlogin()}/Desktop/default.txt'
with open(file, 'r') as inp, open(newfile, 'w+') as out:
for line in inp:
if not line.isspace():
out.write(line.lstrip())
out.write('')
inp.close()
out.close()
os.remove(file)
def delete_userfile_lines(filename):
time.sleep(1.5)
print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}')
file = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/{filename}-tmp.txt'
newfile = fr'c:/users/{os.getlogin()}/Desktop/{filename}.txt'
with open(file, 'r+') as inp, open(newfile, 'w+') as out:
for line in inp:
if not line.isspace():
out.write(line.lstrip())
out.write('')
inp.close()
out.close()
os.remove(file)
def clr_yes_fn_no_print_output(host):
print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
with sub.Popen(["ping", "-n", "4", f'{host}'], stdout=sub.PIPE,
bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
for line in p.stdout:
print(line, end=' ')
def clr_yes_fn_no_print_to_gui(host):
print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
cmd = ["ping", "-n", "4", f'{host}']
proc = sub.Popen(cmd, stdout=sub.PIPE, shell=True, stderr=sub.STDOUT)
for stdout_line in proc.stdout:
print(stdout_line.decode(), end='')
# yield stdout_line
proc.stdout.close()
# return_code = proc.wait()
# if return_code:
# raise sub.CalledProcessError(return_code, cmd)
def clr_yes_fn_no_writefile(host):
print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
file = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/default-tmp.txt'
ping = sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE)
with open(file, 'w+') as output:
data = output.read()
for line in ping.stdout.readlines():
data += str(line.decode())
ping.stdout.close()
output.seek(0)
output.write(data.lstrip())
def clr_no_fn_no_printoutput(host):
print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
with sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE,
bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
for line in p.stdout:
print(line, end=' ')
def clr_no_fn_no_writefile(host):
print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
with open(fr'c:/users/{os.getlogin()}/Desktop/default.txt', 'a') as output:
sub.call(["ping", "-n", '4', f'{host}'], stdout=output)
def clr_yes_fn_yes_printoutput(host):
with sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE,
bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
for line in p.stdout:
print(line, end=' ')
def clr_yes_fn_yes_writefile(host, filename):
file = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/{filename}-tmp.txt'
with open(file, 'w') as output:
sub.call(["ping", "-n", '4', f'{host}'], stdout=output)
def clr_no_fn_yes_printoutput(host):
with sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE,
bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
for line in p.stdout:
print(line, end=' ')
def clr_no_fn_yes_writefile(host, filename):
with open(fr'c:/users/{os.getlogin()}/Desktop/{filename}.txt', 'a') as output:
sub.call(["ping", "-n", '4', f'{host}'], stdout=output)
更新
我添加了StringVar(),现在我在文本框中看到了默认值。
我暂时放弃了那个想法。对我现在的技能来说太多了。 所以我做了一些重新设计,并将函数移到main.py中。 我向主GUI应用了一个线程 线程处理程序:
def thread_handler(self, host):
wt = threading.Thread(target=self.write_to_file, args=(host,))
pt = threading.Thread(target=self.print_to_box, args=(host,))
dt = threading.Thread(target=self.delete_default_lines, args=())
wt.start()
pt.start()
dt.start()
目标:
def print_to_box(self, host):
print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
with sub.Popen(["ping", "-n", '4', f'{host}'], stdout=sub.PIPE,
bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
for line in p.stdout:
self.text_window.insert(tk.END, line)
def write_to_file(self, host):
print(f'Current Proccess: {mp.current_process().name} + {mp.current_process().pid}\n')
with open(fr'c:/users/{os.getlogin()}/Desktop/default.txt', 'a') as output:
sub.call(["ping", "-n", '4', f'{host}'], stdout=output)
def delete_default_lines(self):
time.sleep(4)
print(f'\nCurrent Proccess: {mp.current_process().name} + {mp.current_process().pid}')
newfile = fr'c:/users/{os.getlogin()}/Desktop/Gui-Skeleton/default-tmp.txt'
file = fr'c:/users/{os.getlogin()}/Desktop/default.txt'
lastfile = fr'c:/users/{os.getlogin()}/Desktop/pings.txt'
with open(file, 'r') as inp, open(newfile, 'w+') as out:
for line in inp:
if not line.isspace():
out.write(line.lstrip())
out.write('')
inp.close()
out.close()
shutil.copyfile(newfile, lastfile)
主GUI线程:
if __name__ == "__main__":
lock = threading.Lock()
lock.acquire()
t = threading.Thread(name="Main GUI", target=main, args=())
t.start()
您可以通过
controller
的frames
属性访问其他页面的属性。这将允许TestPing
实例中的text\u窗口
小部件从clr\u yes\u fn\u no\u print\u output()
函数中的for
循环向其发送文本(通过调用其insert()
方法)。我建议你用frames
作为字典而不是列表,这样就可以通过类名而不是数字索引来查找页面。@martineau:在这种情况下不是这样。OP使用多进程,tkinter小部件不能在进程之间共享。我已经更新了屏幕截图,也许会更容易提供帮助@martineau我将在完成核心引擎时这样做,这个问题与我的进度有很大关系:)@martineau它确实会阻止GUI,因为我还没有添加线程。我想解决这个问题,这样我就可以继续,并补充这一点。我有3个进程同时运行-请参阅新建image@Bryan“是的-我没有意识到clr\u no\u fn\u no\u printoutput()
是在一个单独的进程中。对线程也有类似的限制-只有一个线程可以访问tkinter
-因此仅仅使用它们并不能避免阻塞,因为这不是一个选项。对于进程间通信,您需要将通用小部件方法与多处理.Queue
结合使用。