我的目标是创建一个使用按钮运行脚本的 Gui,我已经成功了。接下来,我希望 GUI 能够显示该脚本的输出以及用户响应它的能力。 所以问题是:如何在 gui 中创建一个文本字段,它可以 显示脚本中的
inputs
并 处理接收响应,然后将其发送回脚本。
我想用按钮打开的脚本:
def choose_assignment():
print("1. Mixing two liquids.")
print("2. Dividing a larger volume into x beakers.")
print("To select, enter a digit without a dot on the following line:")
assignment = int(input("Write the digit you choose: "))
print(f"You chose option {assignment}.")
a = input("ahoj: ")
print(a)
if __name__ == "__main__":
time.sleep(1) # Simulate some delay
choose_assignment()
所以我只是希望 gui 中的文本框在运行时显示以下内容:
1. Mixing two liquids.
2. Dividing a larger volume into x beakers.
To select, enter a digit without a dot on the following line:or
Write the digit you choose:
用户可以回答,例如 1 所以 gui 显示
You chose option 1
Ahoj:
等等...
我已经尝试过,但它不起作用,请帮忙。 它没有显示任何错误,但只能显示脚本中的
print
,而不是input
的内容。
import tkinter as tk
from tkinter import scrolledtext
import subprocess
import threading
class ScriptRunnerGUI:
def __init__(self, root):
self.root = root
self.root.title("Script Runner")
# Create a scrolled text widget to display script output
self.text_area = scrolledtext.ScrolledText(root, width=80, height=20)
self.text_area.pack(pady=10)
# Create a button to start the script
self.start_button = tk.Button(root, text="Start Script", command=self.run_script)
self.start_button.pack(pady=10)
# Placeholder for the subprocess
self.process = None
self.is_waiting_for_input = False # Track if we are waiting for input
# Bind the <Return> key to send input from the text area
self.text_area.bind("<Return>", self.send_input)
def run_script(self):
# Disable the start button to avoid multiple starts
self.start_button.config(state=tk.DISABLED)
self.text_area.delete(1.0, tk.END) # Clear the text area
self.display_output("Starting script...\n") # Debug message
# Start the script in a new thread
threading.Thread(target=self.execute_script).start()
def execute_script(self):
# Path to your script (update this path)
script_path = 'C:\\Python\\afaina-evobliss-software-68090c0edb16\\automatizace\\script_run.py' # Ensure this is correct
# Run the script as a subprocess
self.process = subprocess.Popen(['python', script_path],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1)
# Continuously read output from the script
while True:
output = self.process.stdout.readline() # Read output line by line
if output == '' and self.process.poll() is not None:
break # Exit if the process has finished
self.display_output(output) # Display output in the text area
# Check if the script is asking for input
if "enter a digit" in output.lower():
self.is_waiting_for_input = True
self.display_output("Write the answer here:...\n") # Indicate waiting
break # Wait for input
# Re-enable the start button when the process ends
self.start_button.config(state=tk.NORMAL)
def display_output(self, message):
# Display script output in the text area
self.text_area.insert(tk.END, message)
self.text_area.see(tk.END)
def send_input(self, event=None):
if self.is_waiting_for_input:
input_text = self.text_area.get("end-2c linestart", "end-1c") # Get the last line for input
user_input = input_text.strip() + "\n" # Prepare the input to send
if self.process:
self.process.stdin.write(user_input) # Send input to the script
self.process.stdin.flush() # Ensure it's sent immediately
self.is_waiting_for_input = False # Reset the flag
self.text_area.delete("end-2c", "end") # Clear the input line
# Continue reading output
threading.Thread(target=self.continue_reading_output).start()
def continue_reading_output(self):
# Continue reading output after sending input
while self.process.poll() is None:
output = self.process.stdout.readline() # Read output line by line
if output:
self.display_output(output) # Display output in the text area
if __name__ == "__main__":
root = tk.Tk()
gui = ScriptRunnerGUI(root)
root.mainloop()
看起来您的脚本只接受输入一次。当 while 循环中的
break
找到它正在查找的文本时会被触发,并停止收集输入。我建议导入这个函数并在单独的线程上运行它。希望这能回答您的问题。我是这样知道的:
import tkinter as tk
from tkinter import scrolledtext
import subprocess
import threading
from multiprocessing import Process
from script_run import choose_assignment
class ScriptRunnerGUI:
def __init__(self, root):
self.root = root
self.root.title("Script Runner")
# Create a scrolled text widget to display script output
self.text_area = scrolledtext.ScrolledText(root, width=80, height=20)
self.text_area.pack(pady=10)
# Create a button to start the script
self.start_button = tk.Button(root, text="Start Script", command=self.run_script)
self.start_button.pack(pady=10)
# Placeholder for the subprocess
self.process = None
self.is_waiting_for_input = False # Track if we are waiting for input
# Bind the <Return> key to send input from the text area
self.text_area.bind("<Return>", self.send_input)
def run_script(self):
# Disable the start button to avoid multiple starts
self.start_button.config(state=tk.DISABLED)
self.text_area.delete(1.0, tk.END) # Clear the text area
self.display_output("Starting script...\n") # Debug message
# Start the script in a new thread
threading.Thread(target=self.execute_script).start()
print('created thread')
# self.execute_script()
def execute_script(self):
# Path to your script (update this path)
script_path = 'script_run.py' # Ensure this is correct
# Run the script as a subprocess
#, capture_output=True, text=True)
self.process = subprocess.Popen(['python', script_path],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1)
# self.process = threading.Thread(target=choose_assignment).start()
print('created process')
# Continuously read output from the script
while True:
print('enter while')
# o = self.process.stdout
output = self.process.stdout.readline() # Read output line by line
# for output in o.splitlines(): # Read output line by line
if output == '' and self.process is not None: #.poll() is not None:
break # Exit if the process has finished
self.display_output(output) # Display output in the text area
# Check if the script is asking for input
if "enter a digit" in output.lower():
self.is_waiting_for_input = True
self.display_output("Write the answer here:...\n") # Indicate waiting
break # Wait for input
# Re-enable the start button when the process ends
self.start_button.config(state=tk.NORMAL)
def display_output(self, message):
# Display script output in the text area
# for line in message.splitlines():
self.text_area.insert(tk.END, message+"\n")
self.text_area.see(tk.END)
self.text_area.update_idletasks()
def send_input(self, event=None):
if self.is_waiting_for_input:
input_text = self.text_area.get("end-2c linestart", "end-1c") # Get the last line for input
user_input = input_text.strip() + "\n" # Prepare the input to send
print(self.process)
# Send input to the script
if self.process:
print('in the if statement')
self.process.stdin.write(user_input) # Send input to the script
self.process.stdin.flush() # Ensure it's sent immediately
self.is_waiting_for_input = False # Reset the flag
self.text_area.delete("end-2c", "end") # Clear the input line
# Continue reading output
threading.Thread(target=self.continue_reading_output).start()
def continue_reading_output(self):
# Continue reading output after sending input
while self.process.poll() is None:
output = self.process.stdout.readline() # Read output line by line
if output:
self.display_output(output) # Display output in the text area
if __name__ == "__main__":
root = tk.Tk()
gui = ScriptRunnerGUI(root)
root.mainloop()