Функция «печать» не ждет функцию перед тем, как она

#python #tkinter

Вопрос:

В моей программе на Python я определил такую функцию:

 def engine_input_number_of_students_and_student_information(self, window):
        self.__input.input_number_of_students(self, window)
        print(self.number_of_students)
 

и функция input_number_of_students была определена во входных данных класса следующим образом:

 class Input:
    # Function to ask user to input number of student.
    # Print error and force the user to re-input if wrong data is given.
    def input_number_of_students(self, engine, window):
        sub = tk.Toplevel(master=window)
        sub.title("Number of students")
        sub.resizable(height=False, width=False)
        window.eval(f'tk::PlaceWindow {str(sub)} center')
        frm1 = tk.Frame(master=sub)
        frm1.grid(row=0, column=0, padx=10, pady=10)
        lbl = tk.Label(text="Enter number of students:", master=frm1)
        number_of_students_var = tk.StringVar()
        ent = tk.Entry(width=3, master=frm1, textvariable=number_of_students_var)
        lbl.grid(row=0, column=0, padx=5)
        ent.grid(row=0, column=1, padx=5)
        frm2 = tk.Frame(master=sub)
        frm2.grid(row=1, column=0, sticky="nsew", padx=5, pady=5)

        def ok():
            number_of_students = int(number_of_students_var.get())
            if number_of_students < 0:
                messagebox.showinfo(message="Error: number of students must be non-negative")
                ent.delete(-1, tk.END)
            else:
                engine.number_of_students = number_of_students
                print(engine.number_of_students)
                sub.destroy()

        ok_btn = tk.Button(text="OK", master=frm2, command=ok)
        ok_btn.pack(ipadx=5, ipady=5)
 

Но когда я пытаюсь протестировать программу, print функция была выполнена, даже когда я ничего не вводил для number_of_students (очевидно, она выводит 0). И я не знаю, почему.

Комментарии:

1. Итак, ваш реальный вопрос заключается в том, как вы зависаете, input_number_of_students() пока кто-то не нажмет кнопку и не введет несколько студентов?

2. Попробуй print(message, flush=True) . Дело не в том, чтобы «ждать», а в том, чтобы перейти на stdout

3. Я пытался дождаться, пока пользователь введет значение, а затем это значение будет напечатано. Например, когда я ввожу «2» в запись, а затем нажимаю «ОК», после этого будет выведено 2, но print оно было выполнено еще до того, как я что-либо ввел

4. О, я понял свою проблему. Проблема в том, что input_number_of_students создано только подокно, и считается выполненным после этого, а не после нажатия «ОК». Что я хотел бы сделать, так это то, что функция будет выполнена после того, как я введу некоторое значение и нажму «ОК».

5. @GreenCloakGuy да, это то, что я пытаюсь сделать

Ответ №1:

Ваш input_number_of_students не ждет ввода пользователем, он создает окно tkinter, поле ввода и кнопку, но нигде не ждет, пока пользователь что-то введет. Таким образом, программа переходит к следующей строке, которая является print строкой, и выводит a 0 .

Чтобы исправить это, вам нужно позвонить print из функции обратного ok вызова или использовать wait_variable ключевое слово.

 class Input:
    # Function to ask user to input number of student.
    # Print error and force the user to re-input if wrong data is given.
    def input_number_of_students(self, engine, window):
        sub = tk.Toplevel(master=window)
        sub.title("Number of students")
        sub.resizable(height=False, width=False)
        window.eval(f'tk::PlaceWindow {str(sub)} center')
        frm1 = tk.Frame(master=sub)
        frm1.grid(row=0, column=0, padx=10, pady=10)
        lbl = tk.Label(text="Enter number of students:", master=frm1)
        number_of_students_var = tk.StringVar()
        ent = tk.Entry(width=3, master=frm1, textvariable=number_of_students_var)
        lbl.grid(row=0, column=0, padx=5)
        ent.grid(row=0, column=1, padx=5)
        frm2 = tk.Frame(master=sub)
        frm2.grid(row=1, column=0, sticky="nsew", padx=5, pady=5)

        def ok():
            number_of_students = int(number_of_students_var.get())
            if number_of_students < 0:
                messagebox.showinfo(message="Error: number of students must be non-negative")
                ent.delete(-1, tk.END)
            else:
                engine.number_of_students = number_of_students
                print(engine.number_of_students)
                sub.destroy()

        ok_btn = tk.Button(text="OK", master=frm2, command=ok)
        ok_btn.pack(ipadx=5, ipady=5)
        #I'm guessing this is the variable you modify?
        ok_btn.wait_variable(engine.number_of_students_var)
 

Комментарии:

1. О, это хорошо сработало wait_variable . Переменная, которую я хочу изменить, такова engine.number_of_students . Большое спасибо!

2. Использование wait_variable в этом случае не работает, если пользователь закрывает верхний уровень с помощью кнопки «Закрыть» в строке заголовка, ничего не вводя. Лучше использовать wait_window() вместо этого.