From 20dc44181794123831bd706d20dd0a918f7cb8de Mon Sep 17 00:00:00 2001
From: Yousri <54667@etu.he2b.be>
Date: Fri, 15 Apr 2022 14:57:09 +0200
Subject: [PATCH 1/7] SecondVersion
---
learning_python3.md | 193 +++++++++++++++++++++++++++++++-------------
1 file changed, 137 insertions(+), 56 deletions(-)
diff --git a/learning_python3.md b/learning_python3.md
index 4d008c4..bb08c40 100644
--- a/learning_python3.md
+++ b/learning_python3.md
@@ -1184,6 +1184,18 @@ while counter <= 10:
print("after the loop, counter: {}".format(counter))
```
+
+ Another example
+
+```python3
+FirstValue = 2
+SecondValue = 0
+while FirstValue>SecondValue:
+ print("The second value is bigger")
+ SecondValue = SecondValue + 1
+```
+
+
Two *extra* things might look new to you here.
First the `import time` and `time.sleep(1)`, can you tell me what it does?
@@ -1373,14 +1385,14 @@ if __name__ == "__main__":
There is three types of logical operators. All operators returns boolean.
-| Operator | Result |
-|-----------------|----------------------------------------------|
-| **And** | It send 'True' if all conditions are true |
-| **Or** | It send 'True' if one of conditions are true |
-| **Not** | It reverse the boolean result |
+| Operator | Result |
+|-----------------|---------------------------------------------|
+| **And** | It send `True` if all conditions are true |
+| **Or** | It send `True` if one of conditions are true |
+| **Not** | It reverse the boolean result |
-Let's start example with 'And' operator!
+Let's start example with `And` operator !
```python3
CustomerName = "Jean"
@@ -1394,9 +1406,51 @@ if CustomerAgreement and DealerAgreement :
else:
print(f"Oh no {CustomerName} and {DealerName} are disagreed ;( ")
```
-As you can guess, Jean and Paul are agreeing to the deal. If I had put 'False' in DealerAgreement, the result will be inverse.
+As you can guess, Jean and Paul are agreeing to the deal. If I had put 'False' in DealerAgreement boolean, the result will be inverse.
+Let's show an another example with the `Or` operator.
+````python3
+def Choice_cold_hot(Temperature):
+ if Temperature <= 20 or Temperature >= 40:
+ print("Don't go outside")
+ else:
+ print("Let's go to the beach")
+
+if __name__ == "__main__":
+ Temperature = int(input("What is the temperature"))
+ Choice_cold_hot(Temperature)
+````
+Look at this code, if the temperature is smaller than 20° or bigger than 40°, you must stay home and don't go to the beach. So, if I put 35° for temperature, it will say that you should go to the beach.
+
+Let's make an exercise. You have to take the previous code and use the `And` operator.
+
+
+ Spoiler warning
+
+````python3
+def Choice_cold_hot(Temperature):
+ if Temperature >= 20 and Temperature <= 40:
+ print("Let's go to the beach")
+ else:
+ print("Don't go outside")
+if __name__ == "__main__":
+ Temperature = int(input("What is the temperature"))
+ Choice_cold_hot(Temperature)
+````
+
+
+Now, we have used that operators, we can use the last logical operator. The `Not` operator sends the reverse of the result.
+
+````python3
+if __name__ == "__main__":
+ Gas = input("Do you want some gas")
+ if not Gas.startswith("y"):
+ print("Ok, no problem")
+ else:
+ print("That will be expensive")
+````
+In this example, if you tap yes, the result will be reversed.
# Lists
The different built-in objects we've seen until now, such as `str` and `int` are simple [text](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str) and [numeric](https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex) types.
@@ -1537,6 +1591,16 @@ print("{} closes the door behind him...".format(friend.capitalize()))
**TODO pizza function with multiple arguments**
+
+Simpler example
+
+````python3
+for i in range(5):
+ print(i)
+````
+
+
+
# Coding challenge - Cheerleader chant
Can you make me a program that outputs this type of cheerleader chant?
@@ -2630,101 +2694,118 @@ TODO add a countdown timer to the multiple choice game
TODO event loop introduction
-## wxpython helloworld
+## Tkinter helloworld
-The absolute most basic way to have a *hello world* GUI program up and running with wxpython is the following.
+The absolute most basic way to have a *hello world* GUI program up and running with Tkinter is the following.
```python
-import wx
+from tkinter import *
-app = wx.App()
+root = Tk()
-frame = wx.Frame(None, title="hello world")
+MyLabel = Label(root,text="hello world")
+MyLabel.pack()
-frame.Show()
-
-app.MainLoop()
+root.mainloop()
```
+Tkinter have two popular architectures, the Tcl and Tk. This two architectures are different, they have their own functionality and their own official documentation.
+We are gonna use the Tk architecture.
+
+The Tk architecture is used to create a GUI widget. He adds a lot of custom commands, so the widget is very customizable.
+
+In the previous code,the `mainloop()` instruction allows us to open the main window and to not close immediately the window.
+And then, the `Label()` method creates label in a layout. This method has many parameters to customize a label. The instruction `pack()` will be always call , this instruction can
+add and adjust a widget.
While it works we know better by now.
We should include the `if __name__ == "__main__"` statement.
```python
-import wx
-
-
+from tkinter import *
if __name__ == "__main__":
- app = wx.App()
- frame = wx.Frame(None, title="hello world")
- frame.Show()
- app.MainLoop()
+ root = Tk()
+
+ MyLabel = Label(root,text="hello world")
+ MyLabel.pack()
+
+ root.mainloop()
```
-The instance of `wx.App` is what will actually process our event loop and the `wx.Frame` is the content of our window.
+The instance of `Tk()` is what will actually process our event loop and the `root` is the content of our window. We can customize `root` with instruction like geometry, title,etc.
In the latter we will create our button and labels so should create our own class and inherit from it.
```python
-import wx
+from tkinter import *
-
-class MainWindow(wx.Frame):
+class MainWindow(Frame):
def __init__(self):
- wx.Frame.__init__(self, None, title="hello world")
- self.Show()
-
+ Frame.__init__(self,master=None)
+ Label.__init__(self, text="hello world")
+ self.pack()
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("title of the window")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
```
We can add content to the *frame*, such as labels, input boxes and buttons as follows.
-Note the first argument to the `wx.StaticText` creation.
-This is *where* we put the label *into*.
-It kind of works but we'll encounter a **problem** when we pack more visual **objects** into the same frame.
+
```python
-import wx
+from tkinter import *
-
-class MainWindow(wx.Frame):
+class MainWindow(Frame):
def __init__(self):
- wx.Frame.__init__(self, None, title="hello world")
- self.label = wx.StaticText(self, label="this is a label")
- self.Show()
+ Frame.__init__(self,master=None)
+ Label.__init__(self, text="hello world")
+ #Label
+ MyLabel = Label(self, text="This is a label")
+ MyLabel.pack()
+ self.config(bg="yellow")
+ self.pack()
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("title of the window")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
```
Let's try to put multiple visual object into the same frame.
-```python
-import wx
+```python3
+from tkinter import *
-
-class MainWindow(wx.Frame):
+class MainWindow(Frame):
def __init__(self):
- wx.Frame.__init__(self, None, title="hello world")
- self.label = wx.StaticText(self, label="this is a label")
- self.input = wx.TextCtrl(self)
- self.button = wx.Button(self)
- self.Show()
-
+ Frame.__init__(self,master=None)
+ Label.__init__(self, text="hello world")
+ #Label
+ MyLabel = Label(self, text="This is a label")
+ MyLabel.pack()
+ #Button
+ MyButton = Button(self, text="I'm clickable!")
+ MyButton.pack()
+
+ self.config(bg="yellow")
+ self.pack()
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("title of the window")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
```
You see how they are *stacked* one on top of the other?
-We can overcome this problem with [sizers](https://wxpython.org/Phoenix/docs/html/sizers_overview.html).
-There are multiple ones we can use but let's dive into a first one called a **box sizer**.
+We can overcome this problem with parameters of [pack()](https://wxpython.org/Phoenix/docs/html/sizers_overview.html).
+We can also use other geometry managers like [grid()](https://www.pythontutorial.net/tkinter/tkinter-grid/) and [place()](https://www.pythontutorial.net/tkinter/tkinter-place/).
```python
import wx
From f21ccb082d86d88a116b59780311a8b280b92aed Mon Sep 17 00:00:00 2001
From: Yousri <54667@etu.he2b.be>
Date: Tue, 19 Apr 2022 16:18:57 +0200
Subject: [PATCH 2/7] ThirdVersion=>MVC design
---
learning_python3.md | 230 +++++++++++++++++++++++---------------------
1 file changed, 118 insertions(+), 112 deletions(-)
diff --git a/learning_python3.md b/learning_python3.md
index bb08c40..18ed3e9 100644
--- a/learning_python3.md
+++ b/learning_python3.md
@@ -2739,7 +2739,6 @@ from tkinter import *
class MainWindow(Frame):
def __init__(self):
- Frame.__init__(self,master=None)
Label.__init__(self, text="hello world")
self.pack()
@@ -2747,7 +2746,7 @@ if __name__ == "__main__":
root = Tk()
root.title("title of the window")
root.geometry("500x300")
- win = MainWindow()
+ MainWindow()
root.mainloop()
```
@@ -2759,7 +2758,6 @@ from tkinter import *
class MainWindow(Frame):
def __init__(self):
- Frame.__init__(self,master=None)
Label.__init__(self, text="hello world")
#Label
MyLabel = Label(self, text="This is a label")
@@ -2772,7 +2770,7 @@ if __name__ == "__main__":
root = Tk()
root.title("title of the window")
root.geometry("500x300")
- win = MainWindow()
+ MainWindow()
root.mainloop()
```
@@ -2783,7 +2781,6 @@ from tkinter import *
class MainWindow(Frame):
def __init__(self):
- Frame.__init__(self,master=None)
Label.__init__(self, text="hello world")
#Label
MyLabel = Label(self, text="This is a label")
@@ -2799,7 +2796,7 @@ if __name__ == "__main__":
root = Tk()
root.title("title of the window")
root.geometry("500x300")
- win = MainWindow()
+ MainWindow()
root.mainloop()
```
@@ -2808,156 +2805,171 @@ We can overcome this problem with parameters of [pack()](https://wxpython.org/Ph
We can also use other geometry managers like [grid()](https://www.pythontutorial.net/tkinter/tkinter-grid/) and [place()](https://www.pythontutorial.net/tkinter/tkinter-place/).
```python
-import wx
+from tkinter import *
-
-class MainWindow(wx.Frame):
+class MainWindow(Frame):
def __init__(self):
- wx.Frame.__init__(self, None, title="hello world")
- self.panel = wx.Panel(self)
- self.box = wx.BoxSizer()
- self.label = wx.StaticText(self.panel, label="this is a label")
- self.input = wx.TextCtrl(self.panel)
- self.button = wx.Button(self.panel, label="I'm clickable!")
- self.box.Add(self.label)
- self.box.Add(self.input)
- self.box.Add(self.button)
- self.panel.SetSizer(self.box)
- self.Show()
-
+ Frame.__init__(self, master=None)
+ MyPanel = PanedWindow.__init__(self, bg="Blue")
+ #Label
+ MyLabel = Label(MyPanel, text="this is a label", bg= "yellow")
+ MyLabel.pack(fill="x")
+ #Bouton
+ MyButton = Button(MyPanel, text="I'm clickable!")
+ MyButton.place(x=10, y=50)
+ self.pack(fill=BOTH,expand=True)
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("this is the title of the window")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
```
This is looking better!
But it requires some explanation though.
Let's break it down.
-The `wx.Frame` is your **window** in which you create a `wx.Panel` which is used to draw thing to.
-To this panel you're adding three different *objects* (`wx.StaticText`, `wx.TextCtrl` and `wx.Button`) each with or without their own settings (such as a label or not).
-Next you add these three objects to the `wx.BoxSizer` and you tell the panel to use this box as sizer.
+The `Frame.__init__` is your **window** in which you create a `PanedWindow.__init__` which is used to draw thing to.
+To this panel you're adding two different *objects* (`Label()` and `Button()`) each with or without their own settings (such as a label or not).
It probably looks a bit convoluted but this is how most GUI libraries work internally.
1. You create a frame
-2. Within this frame you create a *drawing area* and set some form of automatic layout to it (the `wx.BoxSizer`).
+2. Within this frame you create a *drawing area* and set some form of automatic layout to it.
3. You create the visual elements you want and add them one by one to the drawing area.
4. Success
Now how do we link **user input** to **code actions**?
This is a complicated way of saying *actually do something when I click the damn button*!
-For this we'll need to create a function, or better yet a method to the `wx.Frame` objects.
+For this we'll need to create a function, or better yet a method to the `Frame.__init__` objects.
Each time we click the button, that method will be called.
Because it is a *method* it has access to *self* so it can modify *anything* within the scope of the instance.
```python
-import wx
-import random
+from tkinter import *
+class MainWindow(Frame):
+ def __init__(self):
+ Frame.__init__(self, master=None)
+ MyPanel = PanedWindow.__init__(self, bg="Blue")
+ #Label
+ MyLabel = Label(MyPanel, text="this is a label", bg= "yellow")
+ MyLabel.pack(fill="x")
+ #Bouton
+ MyButton = Button(MyPanel, text="I'm clickable!", command=lambda : self.ButtonEnable(MyLabel))
+ MyButton.place(x=10, y=50)
+ self.pack(fill=BOTH,expand=True)
+
+ def ButtonEnable(self, Label):
+ global number
+ number += 1
+ counter = "You have press the button {} time".format(number)
+ Label.config(text=counter)
-class MainWindow(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, title="hello world")
- self.panel = wx.Panel(self)
- self.box = wx.BoxSizer()
- self.label = wx.StaticText(self.panel, label="this is a label")
- self.input = wx.TextCtrl(self.panel)
- self.button = wx.Button(self.panel, label="I'm clickable!")
- self.button.Bind(wx.EVT_BUTTON, self.set_label_value)
- self.box.Add(self.label)
- self.box.Add(self.input)
- self.box.Add(self.button)
- self.panel.SetSizer(self.box)
- self.Show()
-
- def set_label_value(self, event):
- number = random.randint(0, 100)
- self.label.SetLabel("{}".format(number))
-
+number=0
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("this is the title of the window")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
+
+
```
We can use the same *idea* to grab input from the textbox.
```python
-import wx
+from tkinter import *
+
+class MainWindow(Frame):
+ def __init__(self):
+ Frame.__init__(self, master=None)
+ MyPanel = PanedWindow.__init__(self, bg="Blue")
+ #Label
+ MyLabel = Label(MyPanel, text="this is a label", bg= "yellow")
+ MyLabel.pack(fill="x")
+ #TextBox
+ MyEntry = Entry(MyPanel)
+ MyEntry.place(x=200,y=50)
+ #Bouton
+ MyButton = Button(MyPanel, text="I'm clickable!", command=lambda : self.ButtonEnable(MyLabel,MyEntry))
+ MyButton.place(x=10, y=50)
+ self.pack(fill=BOTH,expand=True)
-class MainWindow(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, title="hello world")
- self.panel = wx.Panel(self)
- self.box = wx.BoxSizer()
- self.label = wx.StaticText(self.panel, label="this is a label")
- self.input = wx.TextCtrl(self.panel)
- self.button = wx.Button(self.panel, label="I'm clickable!")
- self.button.Bind(wx.EVT_BUTTON, self.set_label_value)
- self.box.Add(self.label)
- self.box.Add(self.input)
- self.box.Add(self.button)
- self.panel.SetSizer(self.box)
- self.Show()
-
- def set_label_value(self, event):
- msg = self.input.GetValue()
- self.label.SetLabel("{}".format(msg))
+ def ButtonEnable(self, MyLabel, MyEntry):
+ MyText = MyEntry.get()
+ MyLabel.config(text=MyText)
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("this is the title of the window")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
+
+
```
-## wxpython guess the number
+## Tkinter guess the number
```python
-import wx
+
+from tkinter import *
import random
+class MainWindow(Frame):
+ def __init__(self):
+ Frame.__init__(self, master=None, bg="white")
+ MyPanel = PanedWindow.__init__(self)
-class MainWindow(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, title="Guess the number")
- self.number = random.randint(0, 100)
- self.panel = wx.Panel(self)
- self.box = wx.BoxSizer(wx.VERTICAL)
- self.label = wx.StaticText(self.panel, label="I have a number in mind...")
- self.input = wx.TextCtrl(self.panel)
- self.button = wx.Button(self.panel, label="I'm clickable!")
- self.button.Bind(wx.EVT_BUTTON, self.set_label_value)
- self.box.Add(self.label)
- self.box.Add(self.input)
- self.box.Add(self.button)
- self.panel.SetSizer(self.box)
- self.Show()
+ MyNumber = random.randint(0, 100)
- def set_label_value(self, event):
- result = self.input.GetValue()
- if result.isdigit():
- status, context = self.evaluate_user_number(int(result))
- self.label.SetLabel(context)
+ #Label
+ MyLabel = Label(MyPanel, text="I have a number in mind...", bg= "blue")
+ MyLabel.pack(fill="x", ipadx=25, ipady=20)
+ #TextBox
+ MyEntry = Entry(MyPanel)
+ MyEntry.place(x=200,y=90)
+ #Bouton
+ MyButton = Button(MyPanel, text="I'm clickable!", command=lambda : self.ButtonEnable(MyLabel,MyEntry, MyNumber))
+ MyButton.place(x=10, y=90)
+
+ self.pack(fill=BOTH,expand=True)
+
+
+ def ButtonEnable(self, MyLabel, MyEntry, MyNumber):
+ if self.IsCorrect(MyEntry.get()):
+ number = int(MyEntry.get())
+ if number > MyNumber:
+ MyLabel.config(text="My number is smaller")
+ elif number < MyNumber:
+ MyLabel.config(text="My number is bigger")
+ else:
+ MyLabel.cionfig(text="You WIN!")
else:
- self.label.SetLabel("I need numbers!")
+ MyLabel.config(text="I need numbers!")
- def evaluate_user_number(self, number):
- if number > self.number:
- return False, "my number is smaller"
- elif number < self.number:
- return False, "my number is bigger"
- elif number == self.number:
- return True, "You win!"
+
+ def IsCorrect(self, MyEntry):
+ x = str(MyEntry)
+ if x.isdigit() == True:
+ return True
+ else:
+ return False
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("Guess the number")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
+
+
```
## MVC design pattern
@@ -2966,7 +2978,7 @@ A simple console only MVC.
We'll add the GUI view in a bit.
```python
-import wx
+from tkinter import *
class ConsoleView(object):
@@ -2986,11 +2998,6 @@ class ConsoleView(object):
"""Prints error messages coming from the controller."""
print("error: {}".format(msg))
-
-class WxView(wx.Dialog):
- pass
-
-
class Model(object):
"""The model houses add data and should implement all methods related to
adding, modifying and deleting tasks."""
@@ -3053,7 +3060,7 @@ if __name__ == "__main__":
app.run()
```
-And now with the implemented `WxView` class.
+And now with the implemented `TkinterView` class.
```python
import wx
@@ -3110,7 +3117,6 @@ class WxView(wx.Dialog):
called from the controller."""
self.task.SetLabel(task)
-
class Model(object):
"""The model houses add data and should implement all methods related to
adding, modifying and deleting tasks."""
From 1246e905d34add57e37a19c0539262b86ab96ebb Mon Sep 17 00:00:00 2001
From: Yousri <54667@etu.he2b.be>
Date: Wed, 20 Apr 2022 16:40:44 +0200
Subject: [PATCH 3/7] MVC Finished AND Login Generator Begin
---
learning_python3.md | 75 +++++++++++++++++++++++++--------------------
1 file changed, 42 insertions(+), 33 deletions(-)
diff --git a/learning_python3.md b/learning_python3.md
index 18ed3e9..9871e9d 100644
--- a/learning_python3.md
+++ b/learning_python3.md
@@ -2949,7 +2949,7 @@ class MainWindow(Frame):
elif number < MyNumber:
MyLabel.config(text="My number is bigger")
else:
- MyLabel.cionfig(text="You WIN!")
+ MyLabel.config(text="You WIN!")
else:
MyLabel.config(text="I need numbers!")
@@ -2980,7 +2980,6 @@ We'll add the GUI view in a bit.
```python
from tkinter import *
-
class ConsoleView(object):
"""A view for console."""
@@ -3029,14 +3028,16 @@ class Controller(object):
if self.view is ConsoleView:
self.view = self.view()
self._run_console_view()
- elif self.view is WxView:
- app = wx.App()
+ elif self.view is TkinterView:
+ root = Tk()
+ root.title("Task Manager")
+ root.geometry("500x300")
self.view = self.view()
self.view._set_controller(self)
- app.MainLoop()
+ root.mainloop()
def get_task_from_model(self, idx):
- """Needed for the WxView to communicate with the controller."""
+ """Needed for the TkinterView to communicate with the controller."""
task = self.model.get_task(idx)
self.view.show_task(task)
@@ -3055,7 +3056,6 @@ class Controller(object):
if __name__ == "__main__":
view = ConsoleView
- # view = WxView
app = Controller(view)
app.run()
```
@@ -3063,8 +3063,7 @@ if __name__ == "__main__":
And now with the implemented `TkinterView` class.
```python
-import wx
-
+from tkinter import *
class ConsoleView(object):
"""A view for console."""
@@ -3084,38 +3083,45 @@ class ConsoleView(object):
print("error: {}".format(msg))
-class WxView(wx.Dialog):
+class TkinterView(Frame):
"""A view using a wx.Dialog window"""
def __init__(self):
- wx.Dialog.__init__(self, None, title="Task Manager")
- self.panel = wx.Panel(self)
- self.box = wx.BoxSizer(wx.VERTICAL)
- self.task = wx.StaticText(self.panel, label="your task")
- self.idx = wx.SpinCtrl(self.panel)
- self.button = wx.Button(self.panel, label="submit")
- self.button.Bind(wx.EVT_BUTTON, self.select_task)
- self.box.Add(self.task, 0, wx.EXPAND, 1)
- self.box.Add(self.idx, 0, wx.EXPAND, 1)
- self.box.Add(self.button, 0, wx.EXPAND, 1)
- self.panel.SetSizer(self.box)
- self.Show()
+ Frame.__init__(self, master=None)
+ #Panel
+ self.panel = PanedWindow(self, bg="green")
+ self.panel.pack(fill=BOTH, expand=True)
+
+ #Task Label
+ self.task = Label(self.panel, text="your task")
+ self.task.pack(expand=True)
+
+ #SpinBox
+ self.idx = Spinbox(self.panel, from_=0, to=2, wrap=True )
+ self.idx.pack(side= TOP)
+
+ #Button
+ self.button = Button(self.panel, text="submit", command=lambda : self.select_task())
+ self.button.pack(ipadx=60, ipady=30)
+
+ self.pack(fill=BOTH, expand=True)
def _set_controller(self, controller):
"""Set the controller so the view can communicate it's requests to it
and update it's values too."""
self.controller = controller
- def select_task(self, event):
+ def select_task(self):
"""Gets the index to look up in the model and submits the request to
the controller."""
- idx = self.idx.GetValue()
+ idx = self.idx.get()
self.controller.get_task_from_model(idx)
def show_task(self, task):
"""Updates the visual label in the view with the task. This method is
called from the controller."""
- self.task.SetLabel(task)
+ self.task.config(text=task)
+
class Model(object):
"""The model houses add data and should implement all methods related to
@@ -3128,7 +3134,7 @@ class Model(object):
If no task is found, it returns an error message that will be displayed
in the view (via the controller)."""
try:
- task = Model.db[idx]
+ task = Model.db[int(idx)]
except IndexError:
task = "task with {} not found!".format(idx)
return task
@@ -3139,23 +3145,25 @@ class Controller(object):
def __init__(self, view):
self.model = Model()
- self.view = view
+ self.view = view
def run(self):
- """The controller's main function. Depending on what type of view is
+ """The controller's main function. Depending on what type of view is
selected, a different event loop is setup. Do note that the ConsoleView
is not a real event loop, just a basic flow of action."""
if self.view is ConsoleView:
self.view = self.view()
self._run_console_view()
- elif self.view is WxView:
- app = wx.App()
+ elif self.view is TkinterView:
+ root = Tk()
+ root.title("Task Manager")
+ root.geometry("500x300")
self.view = self.view()
self.view._set_controller(self)
- app.MainLoop()
+ root.mainloop()
def get_task_from_model(self, idx):
- """Needed for the WxView to communicate with the controller."""
+ """Needed for the TkinterView to communicate with the controller."""
task = self.model.get_task(idx)
self.view.show_task(task)
@@ -3173,9 +3181,10 @@ class Controller(object):
if __name__ == "__main__":
- view = WxView
+ view = TkinterView
app = Controller(view)
app.run()
+
```
For a GUI only login generator an implementation without MVC could look a bit like this.
From d807841535b51240923fa72167d414ec49d529a7 Mon Sep 17 00:00:00 2001
From: Yousri <54667@etu.he2b.be>
Date: Thu, 21 Apr 2022 16:39:41 +0200
Subject: [PATCH 4/7] First login generator finish
---
learning_python3.md | 112 ++++++++++++++++++++------------------------
1 file changed, 50 insertions(+), 62 deletions(-)
diff --git a/learning_python3.md b/learning_python3.md
index 9871e9d..535dd5f 100644
--- a/learning_python3.md
+++ b/learning_python3.md
@@ -3192,83 +3192,71 @@ Note that the actual calculation is done inside the window itself.
This is not a good idea because we should separate responsibilities into classes!
```python
-import wx
+from tkinter import *
+from tkinter import ttk
import login_generator
-class MainWindow(wx.Dialog):
+class MainWindow(Frame):
def __init__(self):
- wx.Dialog.__init__(self, None, title="Login Generator")
- 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()
+ Frame.__init__(self)
+ 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.add_login)
- 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)
- 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()
+ 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.add_login())
+ self.login_create.place(x=100,y=100)
+ top_panel.pack(expand=True, fill=BOTH)
- def add_login(self, event):
- amount = self.login_amount.GetValue()
- complex = self.login_complex.GetValue()
+ def show_popup(self):
+ global root
+ menu = Menu()
+ menu.add_command(label="Copy selected items", command=lambda : self.copy_items())
+ root.config(menu=menu)
+
+ def copy_items(self):
+ global root
try:
- amount = int(amount)
- except:
- amount = 1
- for i in range(0, amount):
- username = login_generator.generate_username()
- password = login_generator.generate_password(12, complex)
- index = self.login_list.InsertItem(0, username)
- self.login_list.SetItem(index, 1, password)
+ self.login_amount.insert(END, "Your username is {} and your password is {} \n".format(self.username,self.password))
+ except:
+ Msg = Toplevel(root)
+ l1 = Label(Msg, text="You have to take something")
+ l1.pack(fill=BOTH, expand=True)
+
+ def add_login(self):
+ self.username = login_generator.generate_username()
+ self.password = login_generator.generate_password(12,self.complex.get())
+ self.login_list.insert('', END,values=[self.username, self.password])
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("Login Generator")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
+
```
Now let's assume the generate username and password function take some calculation time.
From 7a88f6a139a9e01806c03118a2dfa3ab0f8d26a7 Mon Sep 17 00:00:00 2001
From: Yousri <54667@etu.he2b.be>
Date: Fri, 22 Apr 2022 16:20:59 +0200
Subject: [PATCH 5/7] The last is not finish (watch thread doc)
---
learning_python3.md | 124 +++++++++++++++++++++-----------------------
1 file changed, 60 insertions(+), 64 deletions(-)
diff --git a/learning_python3.md b/learning_python3.md
index 535dd5f..24669c5 100644
--- a/learning_python3.md
+++ b/learning_python3.md
@@ -3238,7 +3238,11 @@ class MainWindow(Frame):
def copy_items(self):
global root
try:
- self.login_amount.insert(END, "Your username is {} and your password is {} \n".format(self.username,self.password))
+ 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]))
except:
Msg = Toplevel(root)
@@ -3263,85 +3267,77 @@ Now let's assume the generate username and password function take some calculati
We'll add in a fake `time.sleep` to simulate.
```python
-import wx
+from tkinter import *
+from tkinter import ttk
import login_generator
import time
-class MainWindow(wx.Dialog):
+class MainWindow(Frame):
def __init__(self):
- wx.Dialog.__init__(self, None, title="Login Generator")
- 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()
+ Frame.__init__(self)
+ 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.add_login)
- 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.add_login())
+ 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 root
+ menu = Menu()
+ menu.add_command(label="Copy selected items", command=lambda : self.copy_items())
+ root.config(menu=menu)
- def add_login(self, event):
- amount = self.login_amount.GetValue()
- complex_bool = self.login_complex.GetValue()
+ def copy_items(self):
+ global root
try:
- amount = int(amount)
- except:
- amount = 1
- for i in range(0, amount):
- username = login_generator.generate_username()
- password = login_generator.generate_password(12, complex_bool)
+ 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)
- index = self.login_list.InsertItem(0, username)
- self.login_list.SetItem(index, 1, password)
+
+ except:
+ Msg = Toplevel(root)
+ l1 = Label(Msg, text="You have to take something")
+ l1.pack(fill=BOTH, expand=True)
+
+ def add_login(self):
+ self.username = login_generator.generate_username()
+ self.password = login_generator.generate_password(12,self.complex.get())
+ self.login_list.insert('', END,values=[self.username, self.password])
if __name__ == "__main__":
- app = wx.App()
+ root = Tk()
+ root.title("Login Generator")
+ root.geometry("500x300")
win = MainWindow()
- app.MainLoop()
+ root.mainloop()
+
```
A clear separation of responsabilities can be acchieved via an MVC pattern and a login *library*.
@@ -3418,7 +3414,7 @@ And now the GUI code nicely split up in a **model**, **controller** and a **view
The overhead is quite large but it makes the code a lot more scalable.
```python
-import wx
+from tkinter import *
import login_generator
import time
import threading
From 021a26838c2f670cc2f1363f19bf5044138c5bfe Mon Sep 17 00:00:00 2001
From: Yousri <54667@etu.he2b.be>
Date: Mon, 25 Apr 2022 11:36:24 +0200
Subject: [PATCH 6/7] Login Generator with MVC -> finish
---
learning_python3.md | 240 +++++++++++++++++++++++++++++++++-----------
readme.md | 4 +-
2 files changed, 184 insertions(+), 60 deletions(-)
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
From 6d238e157158ec4cb1cb9ae626dad553c3e3c116 Mon Sep 17 00:00:00 2001
From: Yousri <54667@etu.he2b.be>
Date: Mon, 25 Apr 2022 11:56:16 +0200
Subject: [PATCH 7/7] Login Generator with MVC -> finish
---
learning_python3.md | 38 ++++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/learning_python3.md b/learning_python3.md
index 2fbb604..72bd79e 100644
--- a/learning_python3.md
+++ b/learning_python3.md
@@ -2676,7 +2676,7 @@ for question in data["results"]:
choices.append(question["correct_answer"])
choices.extend(question["incorrect_answers"])
for choice in enumerate(choices):
- print(html.unescape("\t {} {}".format(*choice)))```
+ print(html.unescape("\t {} {}".format(*choice)))
```
You can get some *inspiration* from a small project I did for an other course.
@@ -2917,42 +2917,48 @@ if __name__ == "__main__":
## Tkinter guess the number
```python
-
+import time
from tkinter import *
import random
class MainWindow(Frame):
- def __init__(self):
+ def __init__(self):
Frame.__init__(self, master=None, bg="white")
MyPanel = PanedWindow.__init__(self)
MyNumber = random.randint(0, 100)
#Label
- MyLabel = Label(MyPanel, text="I have a number in mind...", bg= "blue")
- MyLabel.pack(fill="x", ipadx=25, ipady=20)
+ self.MyLabel = Label(MyPanel, text="I have a number in mind...", bg= "blue")
+ self.MyLabel.pack(fill="x", ipadx=25, ipady=20)
#TextBox
MyEntry = Entry(MyPanel)
MyEntry.place(x=200,y=90)
#Bouton
- MyButton = Button(MyPanel, text="I'm clickable!", command=lambda : self.ButtonEnable(MyLabel,MyEntry, MyNumber))
+ MyButton = Button(MyPanel, text="I'm clickable!", command=lambda : self.ButtonEnable(MyEntry, MyNumber))
MyButton.place(x=10, y=90)
- self.pack(fill=BOTH,expand=True)
+ self.pack(fill=BOTH,expand=True)
- def ButtonEnable(self, MyLabel, MyEntry, MyNumber):
+ def ButtonEnable(self, MyEntry, MyNumber):
if self.IsCorrect(MyEntry.get()):
number = int(MyEntry.get())
- if number > MyNumber:
- MyLabel.config(text="My number is smaller")
- elif number < MyNumber:
- MyLabel.config(text="My number is bigger")
+ if number != MyNumber:
+ self.GameOver(number, MyNumber)
else:
- MyLabel.config(text="You WIN!")
+ self.Win()
else:
- MyLabel.config(text="I need numbers!")
+ self.MyLabel.config(text="I need numbers!")
+ def GameOver(self, number, MyNumber):
+ if number > MyNumber:
+ self.MyLabel.config(text="My number is smaller")
+ else:
+ self.MyLabel.config(text="My number is bigger")
+
+ def Win(self):
+ self.MyLabel.config(text="You WIN!")
def IsCorrect(self, MyEntry):
x = str(MyEntry)
@@ -2964,8 +2970,8 @@ class MainWindow(Frame):
if __name__ == "__main__":
root = Tk()
- root.title("Guess the number")
- root.geometry("500x300")
+ root.title("Guess the number")
+ root.geometry("500x300")
win = MainWindow()
root.mainloop()