• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Tkinter, Python - jak zrobić nowe okienko, które wyświetla się po wciśnięciu jakiegoś przycisku?

Hosting forpsi easy 1 pln
0 głosów
636 wizyt
pytanie zadane 20 listopada 2022 w Python przez stachu2822 Nowicjusz (160 p.)

Witam serdecznie,

robię prosty, graficzny emulator systemu operacyjnego w pythonie, korzystajac z tkintera.

Problem znajduje się w 37 linijce - nie wiem jak zrobić następującą czynność:

wprowadzam swoją nazwę użytkownika, i chcę, żeby dwie sekundy po tym pojawiło się nowe okienko, w którym wprowadzam swoje hasło. Wydaje mi się, że można zrobić to funkcją if, ale nie wiem jaki warunek tam postawić.

Z góry dziękuję za pomoc.

import time
from time import sleep
from tkinter import *
from PIL import ImageTk, Image
from tkinter import filedialog



root = Tk()
root.title("QOS")
root.iconbitmap("C:\pythonfiles\icofile.ico")
root.geometry("640x360")



usrEntry = Entry(root, width=50)
usrEntry.pack()
usrEntry.insert(0, "Wpisz swoją nazwę użytkownika: ")



def usr_enter():
    usr = Label(root, text="Witamy w QOS, " + usrEntry.get())
    usr.pack()

usrConfirm = Button(
    root,
    text="Zaakceptuj swoją nazwę użytkownika klikając w przycisk",
    padx=5, pady=20,
    activebackground="#959595",
    command=usr_enter
)

usrConfirm.pack()

if  # problem znajduje sie tutaj
    password = Toplevel()
    sleep(2)
    psw_enter = Label(password, text="czesc").pack()

root.mainloop()

 

 

1 odpowiedź

0 głosów
odpowiedź 21 listopada 2022 przez VBService Ekspert (246,010 p.)
edycja 21 listopada 2022 przez VBService

W takiej formie jak zapisałeś nie da nic się wpisać w if-a bo kod w ten sposób umieszczony wykona się po inicjalizacji okna, a tu mamy do czynienia z poczekaniem na zdarzenie (event) np. wpisania nazwy użytkownika lub kliknięcia w przycisk usrConfirm w takim wypadku ten kod

    password = Toplevel()
    sleep(2)
    psw_enter = Label(password, text="czesc").pack()

powinien być przeniesiony do

def usr_enter():
    usr = Label(root, text="Witamy w QOS, " + usrEntry.get())
    usr.pack()

    password = Toplevel()
    sleep(2)
    psw_enter = Label(password, text="czesc").pack()

i wtedy można np. zapisać tak

def usr_enter():
    usr = Label(root, text="Witamy w QOS, " + usrEntry.get())
    usr.pack()

    if len(usrEntry.get()) > 2: #więcej niż 2 znaki
        password = Toplevel()
        sleep(2)
        psw_enter = Label(password, text="czesc").pack()

 

 

Może przenieś całe logowanie do okienka (popup - dialog modal). W przykładzie zakładam, że są utworzone 2 konta (symulacja: lista users)

from datetime import datetime
from time import sleep
from tkinter import *
from PIL import ImageTk, Image
from tkinter import filedialog


def log_time():
    return f"[{datetime.now():%x %X}]"


root = Tk()
root.title("QOS")
root.iconbitmap("C:\pythonfiles\icofile.ico")
root.geometry("640x360")
 
users = ["stachu2822", "VBService"] 

def list_of_users():
    frame = Frame(root)
    frame.pack()
    button_row = 1
    for user in users:
        userButton = Button(
            frame,
            text=user,
            width=20, padx=5, pady=5,
            highlightcolor="green",
            activebackground="#959595",
            font="Consolas 10",
            command=lambda user=user: popup_user_login(user)
        )
        button_row += 1
        userButton.grid(column=0, row=button_row)
        
def popup_user_login(user):
    def close_popup_user_login(): # naciśnięto przycisk x w okienku
        print("User", user, "anulował logowanie", log_time())
        # zamykanie okna popup
        root.wm_attributes("-disabled", False)
        popup.destroy()
        root.deiconify()
        
    def user_login(): # naciśnięto przycisk Login
        print("   Login:", userLoginEntry.get())
        print("Password:", userPasswordEntry.get())

    # otwieranie okna popup    
    root.wm_attributes("-disabled", True)
    popup = Toplevel(root)
    popup.transient(root)
    popup.protocol("WM_DELETE_WINDOW", close_popup_user_login)
    popup.minsize(250, 120)
    popup.maxsize(250, 120)
    popup.title("Login")
    popup.tkraise(root)
            
    Label(popup, text="Podaj login:").pack()
    userLoginEntry = Entry(popup, width=50)
    userLoginEntry.insert(0, user)
    userLoginEntry.pack()    
    Label(popup, text="Podaj hasło:").pack()
    userPasswordEntry = Entry(popup, width=50)
    userPasswordEntry.pack()
    Button(popup, text="Login", font="Consolas 10",
           width=20, padx=5, pady=5, command=user_login).pack(pady=10)

    popup.mainloop()


if __name__ == "__main__":
    list_of_users()
    root.mainloop()

 

komentarz 21 listopada 2022 przez stachu2822 Nowicjusz (160 p.)

Serdecznie dziękuję za odpowiedź, 

zastanawiam się jednak, czy poniższy skrawek kodu mogę wykorzystać cały czas, bez większych zmian i dalej będzie on działał? (inaczej: czy ten, niezmieniony, kawałek kodu cały czas będzie dawał oczekiwane rezultaty, nawet przy innych programach (oczywiście zmieniamy wszelkie zmienne itp.)

# otwieranie okna popup
    root.wm_attributes("-disabled", True)
    popup = Toplevel(root)
    popup.transient(root)
    popup.protocol("WM_DELETE_WINDOW", close_popup_user_login)
    popup.minsize(250, 120)
    popup.maxsize(250, 120)
    popup.title("Login")
    popup.tkraise(root)

    Label(popup, text="Podaj login:").pack()
    userLoginEntry = Entry(popup, width=50)
    userLoginEntry.insert(0, user)
    userLoginEntry.pack()
    Label(popup, text="Podaj hasło:").pack()
    userPasswordEntry = Entry(popup, width=50)
    userPasswordEntry.pack()
    Button(popup, text="Login", font="Consolas 10",
           width=20, padx=5, pady=5, command=user_login).pack(pady=10)

 

komentarz 21 listopada 2022 przez VBService Ekspert (246,010 p.)
edycja 21 listopada 2022 przez VBService

Właściwie to musisz wziąć ten cały kod

def popup_user_login(user):
    def close_popup_user_login(): # naciśnięto przycisk x w okienku
        print("User", user, "anulował logowanie", log_time())
        # zamykanie okna popup
        root.wm_attributes("-disabled", False)
        popup.destroy()
        root.deiconify()
         
    def user_login(): # naciśnięto przycisk Login
        print("   Login:", userLoginEntry.get())
        print("Password:", userPasswordEntry.get())

        '''
        # np. gdy login i password OK wtedy
        if userLoginEntry.get() == "stachu2822" and
           userPasswordEntry.get() == "1234":
           root.wm_attributes("-disabled", False) popup.destroy() 
           root.deiconify()
        '''        
 
    # otwieranie okna popup    
    root.wm_attributes("-disabled", True)
    popup = Toplevel(root)
    popup.transient(root)
    popup.protocol("WM_DELETE_WINDOW", close_popup_user_login)
    popup.minsize(250, 120)
    popup.maxsize(250, 120)
    popup.title("Login")
    popup.tkraise(root)
             
    Label(popup, text="Podaj login:").pack()
    userLoginEntry = Entry(popup, width=50)
    userLoginEntry.insert(0, user)
    userLoginEntry.pack()    
    Label(popup, text="Podaj hasło:").pack()
    userPasswordEntry = Entry(popup, width=50)
    userPasswordEntry.pack()
    Button(popup, text="Login", font="Consolas 10",
           width=20, padx=5, pady=5, command=user_login).pack(pady=10)
 
    popup.mainloop()

z obsługą zamykania okna popup (dialog modal)

ta cześć kodu jest zmienna to są elementy (label, textinput, button itp.) w oknie popup

    Label(popup, text="Podaj login:").pack()
    userLoginEntry = Entry(popup, width=50)
    userLoginEntry.insert(0, user)
    userLoginEntry.pack()    
    Label(popup, text="Podaj hasło:").pack()
    userPasswordEntry = Entry(popup, width=50)
    userPasswordEntry.pack()
    Button(popup, text="Login", font="Consolas 10",
           width=20, padx=5, pady=5, command=user_login).pack(pady=10)

 

komentarz 21 listopada 2022 przez VBService Ekspert (246,010 p.)

Okno popup jest "wywoływane" otwierane przez kliknięcie w tym przypadku button-a

    for user in users:
        userButton = Button(
            frame,
            text=user,
            width=20, padx=5, pady=5,
            highlightcolor="green",
            activebackground="#959595",
            font="Consolas 10",
            command=lambda user=user: popup_user_login(user)
        )

 

komentarz 21 listopada 2022 przez stachu2822 Nowicjusz (160 p.)

Gdybyś mógł jeszcze wytłumaczyć co robią poszczególne linijki, które zawarłem niżej, byłbym wdzięczny

acc.wm_attributes("-disabled", True) # dokładniej ta
    popup = Toplevel(root)
    popup.transient(root) # i ta
    popup.protocol("WM_DELETE_WINDOW", close_popup_user_login) # i ta
    popup.minsize(250, 120)
    popup.maxsize(250, 120)
    popup.title("Login")
    popup.tkraise(root)

 

komentarz 21 listopada 2022 przez VBService Ekspert (246,010 p.)
edycja 21 listopada 2022 przez VBService

win.wm_attributes (Window Manager (wm) attributes)

 

wyłączenie okna z którego zostało otwarte popup, np. okno główne nie reaguje na kliknięcia

root.wm_attributes("-disabled", True

 

Jest to metoda Tkintera używana do kojarzenia okna potomnego (child - popup) z oknem nadrzędnym (parent - root). Np. gdy klikniesz w root to popup - zmineina na chwilę kolor w title (i słychać systemową melodyjkę - warring) - flash - sygnalizuje, że jest potomkiem klikanego okna

popup.transient(root)

 

Przechwycenie zdarzenia, że kliknięto przycisk na oknie

 popup.protocol("WM_DELETE_WINDOW", close_popup_user_login)

    def close_popup_user_login(): # naciśnięto przycisk x w okienku
        print("User", user, "anulował logowanie", log_time())
        # zamykanie okna popup
        root.wm_attributes("-disabled", False)
        popup.destroy()
        root.deiconify()

 

Podobne pytania

0 głosów
1 odpowiedź 134 wizyt
pytanie zadane 1 października 2022 w Python przez MarcelM Początkujący (300 p.)
0 głosów
0 odpowiedzi 213 wizyt
0 głosów
0 odpowiedzi 678 wizyt

92,086 zapytań

140,745 odpowiedzi

317,704 komentarzy

61,407 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 15% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...