使用 Tkinter 读取输入

问题描述 投票:0回答:1

我的目标是创建一个使用按钮运行脚本的 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()

python tkinter input
1个回答
0
投票

看起来您的脚本只接受输入一次。当 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()

© www.soinside.com 2019 - 2024. All rights reserved.