diff --git a/learning_python3.md b/learning_python3.md index 24669c5..2fbb604 100644 --- a/learning_python3.md +++ b/learning_python3.md @@ -3415,71 +3415,68 @@ The overhead is quite large but it makes the code a lot more scalable. ```python from tkinter import * +from tkinter import ttk import login_generator import time import threading import queue -class View(wx.Dialog): +class View(Frame): def __init__(self, controller): - wx.Dialog.__init__(self, None, title="Login Generator") + Frame.__init__(self) self.controller = controller - self.full_window = wx.Panel(self) - self.full_window_sizer = wx.BoxSizer(wx.VERTICAL) - self.full_window_sizer.Add(self.create_top_panel(), 0, wx.EXPAND | wx.ALL, 20) - self.full_window_sizer.Add(self.create_bottom_panel(), 0, wx.EXPAND, 0) - self.full_window.SetSizer(self.full_window_sizer) - self.Show() + self.full_window = PanedWindow(self, orient=VERTICAL) + self.full_window.pack(fill=BOTH, expand=True) + self.create_top_panel() + self.create_bottom_panel() + self.pack(fill=BOTH, expand=True) def create_bottom_panel(self): - bottom_panel = wx.Panel(self.full_window) - bottom_panel_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.login_list = wx.ListCtrl(bottom_panel, style=wx.LC_REPORT) - self.login_list.Bind(wx.EVT_RIGHT_UP, self.show_popup) - self.login_list.InsertColumn(0, 'username', width=200) - self.login_list.InsertColumn(1, 'password', width=200) - bottom_panel_sizer.Add(self.login_list, 0, wx.EXPAND | wx.ALL, 200) - return bottom_panel + bottom_panel = PanedWindow(self.full_window, bg="green") + bottom_panel.pack(fill=BOTH, side=BOTTOM) + # List + self.login_list = ttk.Treeview(bottom_panel, columns=["username", "password"], show="headings", height=6) + self.login_list.pack() + self.login_list.heading("username", text="Username") + self.login_list.heading("password", text="Password") + self.login_list.bind("", lambda e: self.show_popup()) def create_top_panel(self): - top_panel = wx.Panel(self.full_window) - top_panel_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.login_amount = wx.TextCtrl(top_panel) - self.login_complex = wx.CheckBox(top_panel, label="complex") - self.login_create = wx.Button(top_panel, label="Create") - self.login_create.Bind(wx.EVT_BUTTON, self.submit_request) - top_panel_sizer.Add(self.login_amount, 1, wx.EXPAND|wx.ALL,0) - top_panel_sizer.Add(self.login_complex, 1, wx.EXPAND|wx.ALL,0) - top_panel_sizer.Add(self.login_create, 1, wx.EXPAND|wx.ALL,0) - top_panel.SetSizer(top_panel_sizer) - return top_panel - - def show_popup(self, event): - menu = wx.Menu() - menu.Append(1, "Copy selected items") - menu.Bind(wx.EVT_MENU, self.copy_items, id=1) - self.PopupMenu(menu) + top_panel = PanedWindow(self.full_window, bg="red") + self.login_amount = Text(top_panel, height=5, width=52) + self.login_amount.place(x=10, y=10) + self.complex = BooleanVar() + self.complex.set(False) + self.login_complex = Checkbutton(top_panel, text="complex", var=self.complex) + self.login_complex.place(x=10, y=100) + self.login_create = Button(top_panel, text="Create", command=lambda: self.submit_request()) + self.login_create.place(x=100, y=100) + top_panel.pack(expand=True, fill=BOTH) - def copy_items(self, event): - selected_items = [] - for i in range(self.login_list.GetItemCount()): - if self.login_list.IsSelected(i): - username = selected_items.append( - self.login_list.GetItem(i, 0).GetText() - ) - password = selected_items.append( - self.login_list.GetItem(i, 1).GetText() - ) - clipdata = wx.TextDataObject() - clipdata.SetText("\n".join(selected_items)) - wx.TheClipboard.Open() - wx.TheClipboard.SetData(clipdata) - wx.TheClipboard.Close() + def show_popup(self): + global app + menu = Menu() + menu.add_command(label="Copy selected items", command=lambda : self.copy_items()) + app.config(menu=menu) - def submit_request(self, event): - amount = self.login_amount.GetValue() - complex_bool = self.login_complex.GetValue() + def copy_items(self): + try: + Item = self.login_list.item(self.login_list.focus()) + FunctionValue = Item.values() + Array = list(FunctionValue) + Login = Array[2] + self.login_amount.insert(END, "Username : {} \nPassword : {} \n".format(Login[0], Login[1])) + time.sleep(1) + + except: + Msg = Toplevel(root) + l1 = Label(Msg, text="You have to take something") + l1.pack(fill=BOTH, expand=True) + + def submit_request(self): + amount = self.login_amount.get("1.0", END) + complex_bool = self.complex.get() try: amount = int(amount) except: @@ -3488,13 +3485,13 @@ class View(wx.Dialog): def update_logins(self, login): username, password = login - index = self.login_list.InsertItem(0, username) - self.login_list.SetItem(index, 1, password) - + self.login_list.insert('', END, values=[username, password]) class Controller(object): def __init__(self): - self.app = wx.App() + global app + app.title("Login Generator") + app.geometry("450x300") self.view = View(self) self.model = Model(self) @@ -3503,7 +3500,7 @@ class Controller(object): def set_new_logins(self, logins): self.view.update_logins(logins) - + class Model(threading.Thread): def __init__(self, controller): @@ -3524,13 +3521,140 @@ class Model(threading.Thread): def generate_login(self, amount, complex_bool): for i in range(0, amount): self.queue.put((amount, complex_bool)) - + if __name__ == "__main__": + app = Tk() mvc = Controller() - mvc.app.MainLoop() + app.mainloop() + ``` +If you want to add a scrollbar in the project. + +````python + from tkinter import * +from tkinter import ttk +import login_generator +import time +import threading +import queue + + +class View(Frame): + def __init__(self, controller): + Frame.__init__(self) + self.controller = controller + self.full_window = PanedWindow(self, orient=VERTICAL) + self.full_window.pack(fill=BOTH, expand=True) + self.create_top_panel() + self.create_bottom_panel() + self.pack(fill=BOTH, expand=True) + + def create_bottom_panel(self): + bottom_panel = PanedWindow(self.full_window, bg="green") + bottom_panel.pack(fill=BOTH, side=BOTTOM) + ##Scrollbar + self.Scrollbar = Scrollbar(bottom_panel ) + self.Scrollbar.pack(side=RIGHT, fill= Y) + # List + self.login_list = ttk.Treeview(bottom_panel, columns=["username", "password"], show="headings", height=6, yscrollcommand= self.Scrollbar.set) + self.login_list.pack() + self.login_list.heading("username", text="Username") + self.login_list.heading("password", text="Password") + self.login_list.bind("", lambda e: self.show_popup()) + self.Scrollbar.config(command= self.login_list.yview) + + + def create_top_panel(self): + top_panel = PanedWindow(self.full_window, bg="red") + self.login_amount = Text(top_panel, height=5, width=52) + self.login_amount.place(x=10, y=10) + self.complex = BooleanVar() + self.complex.set(False) + self.login_complex = Checkbutton(top_panel, text="complex", var=self.complex) + self.login_complex.place(x=10, y=100) + self.login_create = Button(top_panel, text="Create", command=lambda: self.submit_request()) + self.login_create.place(x=100, y=100) + top_panel.pack(expand=True, fill=BOTH) + + def show_popup(self): + global app + menu = Menu() + menu.add_command(label="Copy selected items", command=lambda : self.copy_items()) + app.config(menu=menu) + + def copy_items(self): + try: + Item = self.login_list.item(self.login_list.focus()) + FunctionValue = Item.values() + Array = list(FunctionValue) + Login = Array[2] + self.login_amount.insert(END, "Username : {} \nPassword : {} \n".format(Login[0], Login[1])) + time.sleep(1) + + except: + Msg = Toplevel(root) + l1 = Label(Msg, text="You have to take something") + l1.pack(fill=BOTH, expand=True) + + def submit_request(self): + amount = self.login_amount.get("1.0", END) + complex_bool = self.complex.get() + try: + amount = int(amount) + except: + amount = 1 + self.controller.get_new_logins(amount, complex_bool) + + def update_logins(self, login): + username, password = login + self.login_list.insert('', END, values=[username, password]) + +class Controller(object): + def __init__(self): + global app + app.title("Login Generator") + app.geometry("450x300") + self.view = View(self) + self.model = Model(self) + + def get_new_logins(self, amount, complex_bool): + self.model.generate_login(amount, complex_bool) + + def set_new_logins(self, logins): + self.view.update_logins(logins) + + +class Model(threading.Thread): + def __init__(self, controller): + threading.Thread.__init__(self, target=self.main) + self.controller = controller + self.queue = queue.Queue() + self.start() + + def main(self): + while True: + amount, complex_bool = self.queue.get() + username = login_generator.generate_username() + password = login_generator.generate_password(12, complex_bool) + logins = (username, password) + self.controller.set_new_logins(logins) + time.sleep(1) + + def generate_login(self, amount, complex_bool): + for i in range(0, amount): + self.queue.put((amount, complex_bool)) + +if __name__ == "__main__": + app = Tk() + mvc = Controller() + app.mainloop() +```` + + + + # Coding challenge - Login generator with GUI # Coding challenge - Trivial pursuit with GUI diff --git a/readme.md b/readme.md index 827ec5c..8e0efcb 100644 --- a/readme.md +++ b/readme.md @@ -100,8 +100,8 @@ This repository contains some notes and exercises for learning python3. * Threading * Day 9 * GUI programming - * wxpython helloworld - * wxpython guess the number + * Tkinter helloworld + * Tkinter guess the number * MVC design pattern * Day 10-12 * Coding challenge - Login generator with GUI