How do Tkinter wait for user interaction during the script?

Asked

Viewed 320 times

1

I am learning Python on my own and now I took it to learn GUI in Tkinter. If anyone can help me, I’m having trouble getting the program to display a greeting and then offer options on different buttons. By the way... I think I managed to do this, but the problem is that I wanted the program to wait for the user to interact and then just run the next line.

Let’s say for example that I create a file with the Window class (for the interface) and some functions (Window.py):


import time
from tkinter import *

# Aqui a função dos botões. Referenciei ela primeiro para não dar conflito. Quando tentei isso, quebrei esse código em mais de um programa e chamei as funções de lá, mas aqui vou fazer tudo em um arquivo só para não ficar confuso:    

Escolha = ''

def Escolher(X):
    Escolha = X


# Aqui o objeto 'Janela':

class Janela:

    def __init__(self):
        self.Janela = Tk()
        self.Janela.title = 'Interaja'
        self.Janela.minsize = (500, 300)
        # Aqui uma label para imprimir as mensagens que quero passar para o usuário:  
        self.Texto = Label(self.Janela, text = '')
        self.Texto.pack()
        # Aqui uma série de botões:
        self.B1 = Button(self.Janela, text = 'Opção 1', command = Escolher('1'))
        self.B1.pack()
        self.B2 = Button(self.Janela, text = 'Opção 2', command = Escolher('2'))
        self.B2.pack()
        self.B3 = Button(self.Janela, text = 'Opção 3', command = Escolher('3'))
        self.B3.pack()

# Aqui crio uma instância do objeto Janela:  

Exemplo = Janela()

# Aqui uma função para que determinadas mensagens sejam exibidas:  

def Diga(X):
    Exemplo.Texto.configure(text = X)
    Exemplo.Texto.update()
    time.sleep(3) # Ignorem. Deixei esse atraso pro usuário conseguir ler a tempo. Tenho um método mais eficiente pra isso, mas só pra simplificar deixei assim.  

# Por fim, a parte principal do programa:  

Diga('Sejam bem-vindos!')
Diga('Você quer escolher qual opção?')
EspereEscolha() # Aqui, queria que o programa esperasse a opção ser escolhida para só então imprimir a seguinte mensagem:  
Diga('Você escolheu a opção {}'.format(Escolha))
Texte.mainloop()

Does anyone happen to know how to create this 'Espereescolha()', or if it already exists and I’m the one who is not able to do?

Grateful for the attention.

1 answer

1

is the following, when you create a Tk() you have to declare its mainloop

Texte.mainloop()

what happens is that you calling a function that comes before this mainloop kind of will never work user input by Tkinter, since you are not actually running the interface loop. You then need to create your class so that it has the methods and you will call it from the init of the object. This for everything in fact, from the creation of widgets to the commands referring to them. I rewrote your code with these changes to show you how it could be

import time
from tkinter import *

class Janela:

def __init__(self):
    self.Janela = Tk()
    self.Janela.title = 'Interaja'
    self.Janela.minsize = (500, 300)
    # Aqui uma label para imprimir as mensagens que quero passar para o usuário:  
    self.Texto = Label(self.Janela, text = '')
    self.Texto.pack()
    self.Apresentacao()

# A apresentação que você queria que o usuário pudesse ler.
# tenha em mente que o sleep para o processo total, logo o tkinter vai dar aquele sinalzin de carregamento
# se alguem passar o mouse por cima do GUI. Talvez você pode fazer uma validação futura
# pegando o time atual e salvando o valor, validando se ele é menor que o tempo futuro, como um cooldown
def Apresentacao(self):
    self.Diga('Sejam bem-vindos!')
    time.sleep(3)
    self.Diga('Você quer escolher qual opção?')
    time.sleep(3)
    self.MostarOpcoes()

# método que pode ser chamado em qualquer outra função para alterar um label especifico
# talvez fazer um método mais genérico onde você passa qual label especifica você quer alterar
def Diga(self, texto):
    self.Texto.configure(text = texto)
    self.Texto.update()

# outra função para mostrar widgets enquanto o frame esta no mainloop.
def MostarOpcoes(self):
    # esse lambda é uma gambiarrazinha para passar um valor para uma função
    # geralmente se não utilizar alguma técnica do tipo para por uma função no command
    # faz com que a função seja chamada na hora de instanciar o objeto, então toma cuidado com o command
    self.B1 = Button(self.Janela, text = 'Opção 1', command = lambda valor=1: self.Escolher(valor))
    self.B1.pack()
    self.B2 = Button(self.Janela, text = 'Opção 2', command = lambda valor=2: self.Escolher(valor))
    self.B2.pack()
    self.B3 = Button(self.Janela, text = 'Opção 3', command = lambda valor=3: self.Escolher(valor))
    self.B3.pack()
# função que os botões utilizam
def Escolher(self, valor):
    self.Diga('Você escolheu a opção {}'.format(valor))

Exemplo = Janela()

Exemplo.Janela.mainloop()

So just to recap, make methods that are used during the execution of the frame mainloop, because anything you write below the mainloop() will only be executed after you close Tkinter and anything on the mainloop() will not execute anything from the Tkinter :3 GUI

Browser other questions tagged

You are not signed in. Login or sign up in order to post.