Dün TkInter'da GUI'yi Ayrı Dosyaya Bölme başlığında bir örnek paylaşmıştım, kullanıcı login yaptıktan sonra toplevel açılıyordu. Yapacağınız ufak değişiklikler ile toplevel yerine login ekranının yok olmasını yerine yeni bir frame widgetinin gelmesini sağlayabilirsiniz.
Örnek:
Programın dosyalarının ağaç dizin yapısı şu şekilde:
.
├── run.py
└── Scripts
├── button.py
├── entry.py
├── frame.py
├── __init__.py
├── modules.py
└── utilities.py
Bunlar da dosyaların içinde yer alan kodlar:
Dosya: run.py
#!/usr/bin/python3.8
# -*- coding: utf-8 -*-
if __name__ == "__main__":
from Scripts import main
main()
Dosya: Scripts\modules.py
# -*- coding: utf-8 -*-
import tkinter as tk
from tkinter.messagebox import showwarning
Dosya: Scripts\__init__.py
# -*- coding: utf-8 -*-
from .modules import tk
from .button import Button
from .frame import LoginFrame
from .utilities import authenticate
def main():
root = tk.Tk()
login = LoginFrame(
master=root,
texts=["Username", "Password"],
max_chars=[20, 20]
)
apply_button = Button(
master=root,
text="\u2714",
color="green",
command=lambda: authenticate(*login.entries.values(), master=root)
)
root.mainloop()
Dosya: Scripts/button.py
# -*- coding: utf-8 -*-
from .modules import tk
class Button(tk.Button):
def __init__(self, color, *args, **kwargs):
super().__init__(*args, **kwargs)
self.configure(
activebackground=self["bg"],
activeforeground=color,
borderwidth=0,
highlightthickness=0,
font="Default 20",
fg=color
)
self.pack()
Dosya: Scripts\entry.py
# -*- coding: utf-8 -*-
from .modules import tk
class Entry(tk.Entry):
def __init__(self, max_char: int, *args, **kwargs):
super().__init__(*args, **kwargs)
self.bind(
sequence="<KeyRelease>",
func=lambda event: self.__apply_max_char(max_char=max_char)
)
self.configure(width=max_char)
if self._name == "password":
self.configure(show="*")
def __apply_max_char(self, max_char):
if len(self.get()) > max_char:
self.delete(max_char, "end")
Dosya: Scripts/frame.py
# -*- coding: utf-8 -*-
from .modules import tk
from .entry import Entry
class LoginFrame(tk.Frame):
def __init__(self, texts: list, max_chars: list, *args, **kwargs):
super().__init__(*args, **kwargs)
self.pack()
self.entries = self.__create_entries(
texts=texts,
max_chars=max_chars
)
def __create_entries(self, texts, max_chars):
entries = {}
for index, (text, max_char) in enumerate(zip(texts, max_chars)):
label = tk.Label(master=self, text=text)
label.grid(row=index, column=0, sticky="w")
entry = Entry(
master=self,
max_char=max_char,
name=text.lower()
)
entry.grid(row=index, column=1, sticky="w")
entries[text] = entry
return entries
class WelcomeFrame(tk.Frame):
def __init__(self, username: str, *args, **kwargs):
super().__init__(*args, **kwargs)
self.pack()
self.label = tk.Label(master=self, text=f"Welcome {username}")
self.label.pack()
Dosya: Scripts/utilities.py
# -*- coding: utf-8 -*-
from .modules import tk, showwarning
from .frame import WelcomeFrame
def get_entry_values(*entries):
return [ent.get() for ent in entries if isinstance(ent, tk.Entry)]
def has_authentication(*entries):
return get_entry_values(*entries) == ["Admin", "123456"]
def authenticate(*entries, master):
if has_authentication(*entries):
username = entries[0].get()
for child in master.winfo_children():
child.destroy()
WelcomeFrame(master=master, username=username)
else:
showwarning(
title="Warning",
message="Wrong username and password"
)
Mesela bakın burada __init__.py dosyasında root ile birlikte bir LoginFrame ve bir Button tanımlanıyor. Button'un yapacağı işlem olan authenticate ise utilities.py dosyasında tanımlı. utilities.py dosyasındaki authenticate'e baktığımız zaman, bu fonksiyon LoginFrame'e girilen kullanıcı adı ve şifresinin doğru olup olmamasına göre iki farklı işlem yapıyor. Şayet kullanıcı adı ve şifre doğruysa, LoginFrame ve Button yok ediliyor yerine WelcomeFrame getiriliyor ya da ekrana bir uyarı penceresi getiriliyor.
Kodları bir inceleyin isterseniz.