Learniverse

Building Desktop Applications with Python

00:00

Are you ready to start building your own desktop applications?

00:06

You've landed on the right video.

00:08

This is the course for you.

00:10

Over the next seven hours, we are going to be building five interactive applications with

00:15

Python.

00:17

This course is designed for those wanting to take their Python skills up a level and learn

00:21

Python, GUIs, or graphical user interfaces.

00:26

You're going to be exploring core technologies in Python, like the powerful PiQD framework

00:32

and SQL in map plot live, just to name a few.

00:36

Well without further ado, I don't want to keep you guys waiting.

00:39

Let's start building apps.

00:40

It's why you're here.

00:42

Are you ready?

00:43

Because I'm ready.

00:44

Let's dive in.

00:47

Welcome guys to another code with Josh special.

00:50

For super obvious reasons, I'm Josh.

00:53

If you guys don't want to hear me ramble out for the next few minutes, it is going to be

00:56

beneficial.

00:57

Here's the timestamp that just jumps into the course.

01:00

You can check that out.

01:01

But, as I mentioned, we're going to be building five interactive apps, a starter app,

01:06

a calculator app, expense tracker, an image editor, as well as an interest rate calculator

01:13

using map plot live, SQL.

01:15

Guys, this course is hosted absolutely free, right?

01:19

Show some love.

01:20

Smash that like button and subscribe, comment and engage.

01:25

Because that does help my course reach more students around the world, okay?

01:30

That is your way you can show support.

01:32

And guys, the first link in the description will use the links, okay?

01:36

But I'm hosting this course on my own platform for you guys, absolutely free.

01:42

Over there is the community, all my other free resources, all right?

01:45

So to show your support, just use the links in the description, all right?

01:49

Okay, enough chit chat.

01:51

Let's just jump into the course.

01:53

I'm really excited.

01:55

I hope you are, too.

02:20

Hi there, and welcome to our course.

02:23

Before we get started, I'd like to kick off my courses by going over the course structure

02:29

and what you can expect in this course.

02:33

Let's jump in and let's take a look.

02:36

Our initial overview is you can expect a project-based course

02:41

as this allows you to build your skills in a way that keeps you going,

02:47

but also challenges you and you can see a final product.

02:52

You will be building a strong foundation in the fundamental concepts

02:55

of building apps in Python with PICUTE and you will use your existing Python skills.

03:02

Now, you should have a basic understanding.

03:06

As this course and PICUTE is a class-based framework,

03:11

the knowledge you gain from this course will be key in your programming journey

03:16

and allow you to expand on what you already know.

03:20

We are going to talk about the setup for any PICUTE project.

03:24

We will look at ways to create our app widgets, design our GUI,

03:31

and add some app functionality throughout this course.

03:36

We will talk about PICUTE widgets, how we can create custom widgets,

03:40

how we can style our widgets and use in buttons and labels within our programs.

03:47

To break down our course overall,

03:49

we will begin with giving you a good understanding of how we use PICUTE to create applications.

03:56

We then build on working with layouts and designs for our overall apps

04:03

while introducing widgets in creating interactive GUIs.

04:08

Once you've built this solid foundation of creating your layouts, working with widgets,

04:15

we now have a basic understanding of PICUTE.

04:19

You will then be introduced to SQL,

04:23

and how we can use SQL to create databases in PICUTE.

04:29

Now, we're only brushing the surface here,

04:31

and you don't need to have any background in SQL.

04:34

You'll learn everything you need to know here to hit the ground running.

04:38

For our final project, you will learn data visualization

04:43

with a module called Matplotlib.

04:45

This will introduce you to data analysis and data visualization with Python.

04:52

You'll also see how we can use CSS to style our Python applications.

04:59

Throughout this course, you will have five projects in total.

05:03

The first project isn't here,

05:05

but it's a project to get you warmed up with the initial setup in the design for PICUTE.

05:12

Then we work with four projects that all build upon each other.

05:17

Our first one is going to be a calculator app,

05:21

and we will add styling to this app.

05:25

We then move on to an image editing application,

05:28

or I've nicknamed my app PhotoQT.

05:32

This app allows you to edit real photos in Python.

05:36

We then will progress into our third capstone project.

05:40

This is an expense tracker,

05:42

and here is where you'll learn how to create a database using SQL.

05:48

Our final project is going to be an interest rate calculator

05:52

with our data visualization.

05:55

This is where we will talk about how we can use charts and graphs in our applications.

06:02

Who is this course designed for?

06:03

Well, it's designed for a lot of you.

06:05

It's designed for programmers of all levels.

06:08

For those looking to grow their Python portfolio,

06:11

those looking who want complex tasks broken down

06:16

to a basic level of understanding.

06:19

That is what my courses and the zero-to-knowing series does.

06:23

Breakstown complex tasks into easily understandable topics.

06:29

This course is designed for project-based learners,

06:32

as well as all you visual learners out there.

06:35

Don't worry, you'll get access to all my slides,

06:39

live coding, projects, and more.

06:42

Now that you have an overall understanding

06:44

of what you can expect in this course,

06:46

and the overall structure, let's jump in

06:48

and let's start off with the installation

06:50

of what we need to hit the ground running.

06:53

I'll see you guys in the next video.

06:55

Music

07:19

All right, we're just about there.

07:22

Before we jump into the first lesson,

07:25

I want to get everything installed and set up here

07:28

within VS code.

07:30

Now, you may have already used VS code,

07:33

or this might be new to you.

07:34

Let's go through just one extension that we're going to be using,

07:38

and I'll give you mine as well.

07:40

The first extension that you should have,

07:42

please look for Python.

07:45

And just go through and make sure that you do have Python

07:48

within VS code.

07:50

You can install this here.

07:53

I am using a theme, as you can see here,

07:56

we have a few different things going on.

07:59

Now, if you wanted to follow along with my theme,

08:01

because color coordination works for me.

08:04

It might work for you.

08:05

I use synthwave 84 as my theme currently for the duration

08:12

of this course.

08:12

You are welcome to get it there too.

08:15

Okay, let's get that out of the way.

08:17

We have looked at our two extensions.

08:20

Now, going forward, we are going to be working

08:24

with a few different libraries throughout this course.

08:27

I want to install them all right now, so I have them.

08:31

We are going to be using Python.

08:34

We are going to be using Pillow,

08:37

and we are going to be using Matt Plotlib.

08:41

Let's get these all installed.

08:43

To open your terminal on a Mac,

08:45

you can press Command J or on a Windows Control J.

08:50

Down here, I just want to install,

08:53

so using the Python package installer.

08:55

I'm going to say Pip3 for yours.

08:58

You might say Pip, but with most updated newer versions of Python,

09:03

Pip3 seems to be the way to go.

09:06

I'm going to say Pip3 install PiQT5.

09:11

Enter.

09:12

Let it do its thing.

09:13

Now, as you can see, it says requirement already satisfied for mine.

09:18

That's because I already have it here.

09:20

For the Pillow library, I'm going to say Pip3 install Pillow.

09:26

Get that there.

09:28

Now, if none of these are working for you,

09:29

okay, you may need to try Python3-mPip install Pillow.

09:36

You can try using instead of Pip3 saying Python3.

09:42

This brings us to our final one, which is map plot lib,

09:45

so Pip3 install map plot lib.

09:50

As you can see, I also have that one already installed.

09:53

At this point, you're ready to go.

09:55

You have PiQT framework installed,

09:58

which we will be using for our course,

10:00

and then we will also introduce how to use Pillow and the Pillow library

10:04

as well as map plot lib at later stages.

10:07

I'm ready for the first lesson, and at this point, you are too.

10:11

I'll see you guys in lesson one of our course.

10:31

Hi, and welcome to the zero-to-knowing,

10:33

building apps in Python course.

10:35

In this course, we will be looking at how to create apps in Python

10:40

using the PiQT framework.

10:43

Before building any apps, let's jump in,

10:45

and let's talk about what is PiQT.

10:49

So, long story short, PiQT is a module that bridges.

10:54

It connects a popular framework in C++ and Python,

11:01

so it allows us to use this popular C++ framework

11:06

in the language we choose to use, which is Python.

11:10

And it enables us to create graphical user interfaces.

11:16

Now, you're gonna hear this a lot throughout this course.

11:20

And what you're gonna hear me say is,

11:22

you're gonna hear me say GUI.

11:25

GUI is a reference for graphical user interfaces.

11:32

PiQT allows us to do many different things,

11:35

such as creating databases with SQL,

11:39

or adding in embedded web browsers,

11:42

and even using its own collection of widgets

11:47

and a widget is what you see on the app screen.

11:52

And there's so much more that we can do with PiQT.

11:56

And these features make QT a comprehensive framework,

12:00

and it allows us to make all types of apps in Python.

12:05

Let's talk about, what is the difference

12:07

between PiQT-5 and PiQT-6?

12:13

Well, there is no major difference between these two.

12:17

In this course, we will specifically focus

12:20

on PiQT-5 as these two versions of framework

12:24

or so similar.

12:26

Anything you do in PiQT-5,

12:29

there are easy workarounds to any solutions

12:33

that may occur with PiQT-6.

12:37

And by learning and understanding,

12:39

just the last version, PiQT-5,

12:44

you're gonna be able to work with a wider range of applications.

12:49

You'll be able to work with older PiQT apps

12:53

as well as the new apps using PiQT-6.

12:58

The final question you may be asking yourselves now

13:01

is, why do we use PiQT?

13:05

Why do developers choose this framework over others?

13:09

I've put together a few popular reasons why.

13:12

Going through them,

13:14

PiQT allows for cross platform compatibility.

13:18

So it allows our apps to be run

13:21

on different operating systems, like I'm on a Mac,

13:26

but you yourself may be on a Windows or a Linux,

13:30

PiQT allows for this.

13:32

It also provides endless widgets.

13:36

You're gonna hear this a lot in our course.

13:39

What is a widget?

13:40

A widget is something you see on your app screen.

13:45

It could be buttons, text, menus, anything like that.

13:50

And PiQT provides these ready-made

13:53

or pre-built GUI elements.

13:58

They also offer a wide range beyond just these components.

14:02

Like I've mentioned in the previous slides,

14:05

we could include databases, graphics, like pictures,

14:10

networking, and a few of these,

14:13

we will actually be building projects

14:15

in this course using them.

14:19

PiQT also has something called QT designer.

14:23

And QT designer makes it significantly easier

14:27

to build a PiQT app.

14:30

It's kind of like Figma or Canva for building with PiQT.

14:34

We won't be addressing that in this course

14:37

because that's not programming,

14:39

that's not coding, that's not learning the logic.

14:43

In this course, most developers aren't going to use QT designer.

14:48

You're expected to know how to build out an app

14:51

and what things are doing within your app.

14:53

That's what we focus on here.

14:56

Finally, PiQT is based in Pithon, right?

15:00

We are bridging it and connecting it to Pithon,

15:04

which makes it very straightforward to us.

15:07

As Pithon is an easier language

15:09

and has easier syntax to understand.

15:12

Now that we understand what PiQT is and why we use it,

15:16

let's head over into our next video

15:18

and talk about windowed applications.

15:20

I'll see you guys in the next video.

15:24

Music

15:47

Here we are at the Introduction to our first app.

15:51

Before we start making our first app, we need to understand what is a windowed application.

15:58

And PICUTE is made to create these windowed applications.

16:04

We are here to touch on the Foundations we will use to construct and build your first app.

16:10

These are two current and popular examples of windowed applications.

16:15

I took these off my Mac and you see a calculator and we have the System Preferences tab.

16:22

They pop out when we need them and we close them when we do not need them anymore.

16:29

As we break this down further, let's examine and take a look at the System Preferences app that you see here in the left.

16:38

We have a main window and inside this main window, we have app widgets or objects.

16:47

These work together to create the GUI of our app.

16:52

And if you think about the main window as like a jar, right?

16:58

And then all of the widgets are the coins and the money inside the jar.

17:04

They all represent something different, but they're all inside the same jar.

17:09

This jar is like the parent, it's like the main window of our app.

17:14

Within the app, you also see many widgets, which is a word that I also keep using.

17:20

In this app, we see a text input box, a checkbox, text, push buttons, a list.

17:29

All of these are a type of widget or an object that we create and then we later add into the app.

17:39

Remember this word later, but these are widgets from a class called QT widgets.

17:49

If I asked you to design this app, what comes to mind?

17:53

What type of layout would you use? Would you draw this out? Would you put it in rows?

18:00

How could we design it? It's a great question.

18:04

And as we start looking further at apps, it's a question that you should be asking yourself.

18:09

How I would design this app is yes, rows and columns exactly.

18:14

What can we store in a row? And what can I store in a column?

18:18

Can I store columns in a row?

18:22

Let's look at that.

18:25

This has two rows and two columns.

18:29

We use the layouts in by QT to build our design, okay?

18:36

Widgets, they are automatically aligned either vertically or horizontally.

18:43

So my two rows are horizontal and my two columns are vertical.

18:50

In row one, I have one, two, three, four buttons.

18:57

They're in their own row at the top of my app.

19:01

In the second row, I actually have two columns, one column, two columns with some text and a button.

19:13

These columns are added into a row at the end. Interesting.

19:20

So start thinking about how can we break an app down to the design basics of rows and columns.

19:29

Moving forward, let's take a look at what exactly the PiQT framework is and how it all ties together.

19:37

PiQT is a massive framework. And within this framework, we have modules.

19:43

So for example, you may have used other popular Python modules like the built-in ones, time and random,

19:50

or maybe you've used other external modules frameworks like pandas, or plot-lead,

19:57

or others like that. Well, PiQT is like that.

20:01

It is one main framework. And then within that, there are many modules.

20:06

Within each module, there are many classes, many functions, all of that stuff.

20:13

Here, I've put just a few of the popular PiQT modules. Will we use all of these in our course?

20:21

No, will we use some of them? Absolutely. Are there going to be others?

20:26

Also, yes, there will be others. These are just a few popular ones.

20:30

Starting off. I'm going to talk about QT widgets because we actually saw this earlier.

20:36

Remember, everything on the app screen is considered a widget.

20:42

And this really provides us with GUI elements or objects that we can add into our app screen.

20:51

Another module that we will start off with using early on is a module called QT Core.

20:58

QT Core essentially holds the miscellaneous elements that we need within certain elements of our app.

21:05

As we grow in our fundamentals and understanding of app development,

21:10

you can expect to learn a little bit of SQL in this course in creating databases,

21:15

as well as learning some GUI and design elements.

21:21

Something that I've created that I love to teach the order of in this pattern is the code burger.

21:28

All right? I'm going to put this at stages throughout this course.

21:32

If you take notes, which not really if you should be taking notes,

21:37

and if you do, you should write this down or screenshot the code burger.

21:41

This is the order of steps we must take in order to design an app and PiQT and get it to open and run accordingly.

21:50

Number one, we need to make sure all of our imports are at the top of our burger at the top of the code.

21:58

Once we import everything we need, I will then create my main app objects and all my app settings like the size of my app,

22:10

the tile of my app, things like that.

22:13

Once we get everything set up,

22:16

I can then create all the widgets that I want to have in my app.

22:21

They can be stored at the top, all the buttons, all the text, anything like that can be stored in this step.

22:29

Once we create all these widgets, we need to add them to our design.

22:34

We need to design our app or design our layout and add all those widgets to the main window, our screen.

22:45

Once we finalize that design, it's the good idea to set our final layout, we want to set the final design to our main window,

22:56

ending with showing and executing our app.

23:01

PiQT is a class-based language.

23:04

Now, at this point in your programming journey, you should understand the fundamental concepts of Python and programming in general.

23:12

Python has a core concept of object-oriented program.

23:16

That is where we create objects in classes and the class can store fundamental information about those objects.

23:25

If we do a quick class flashback, pause the video, read through this code and understand what's happening.

23:33

Do you understand everything?

23:35

What things do you not quite understand?

23:38

And then answer the question for me, what is a method and what is a property?

23:45

To touch on these very briefly, we defined a class called app.

23:52

Remember, a class name is one of the only things in Python that is capitalized.

23:59

My class is called app.

24:01

I have three methods, one, two, three.

24:06

A method is a function in a class.

24:10

I then create an object.

24:13

The value of an object is a class.

24:17

In this case, is app.

24:19

I'm giving app three arguments, one, two, three, because my app has one, two, three parameters.

24:31

These parameters are used as the value to my properties.

24:40

What is a property?

24:42

A property is a variable in a class.

24:46

I can then use these throughout parts of my class.

24:52

When it comes time to use a method, a method must be linked to your object.

25:00

So a method is a function in a class.

25:02

You must link it to an object of that class in order to use it.

25:08

All right, that was a lot.

25:10

But don't worry, because I've color coordinated a part of it.

25:13

And I want you to take a look at that now.

25:17

Making an object, we're giving the three arguments to our class.

25:22

Now these arguments we are giving to in it.

25:26

In it is what we call our constructor method.

25:30

Constructor, construction, build.

25:34

We use in it to build our class.

25:40

Now, PICUT is a framework that has modules.

25:45

Each module has classes.

25:49

These classes we can import into our projects to allow us to use them in our apps.

25:55

Each class has methods and properties of its own that we can use when we link it to an object of that class.

26:10

That's a lot.

26:12

But this flashback, it should get the gears turning.

26:15

It should bring back memories in the core concepts of how we use object-oriented programming and Python.

26:22

Brilliant.

26:24

Let's talk about how we can connect to PICUT to set our app up.

26:30

Remember, step number one of the code burger.

26:33

We want to import everything we need.

26:36

Now, PICUT, you can see I am linking to one of the modules.

26:41

PICUT is the framework.

26:43

CUT core and CUT widgets are a module from our framework.

26:49

CUT is a class from my module QT core.

26:56

I am importing something called QT.

26:59

You'll find out more about this very soon.

27:02

Then, we import all of the QT widgets we need.

27:07

These widgets are the objects that we want to see within our app.

27:13

Do you want to see buttons?

27:15

Do you want to see an input field?

27:17

Text?

27:18

What do you want to see in your app?

27:20

That's what we import here.

27:22

The two most important classes that we must import in order to get a working app are Q application and Q widget.

27:31

Q application allows us to create and execute our app.

27:36

Q widget on the other hand allows us to actually create that main window.

27:42

The parent that all the other objects are dropped into.

27:47

Great, we need those two.

27:50

That's why I always like to import them first.

27:54

Next is anything you want to see in your app.

27:57

Anytime you want to see text on the screen of your app, text in PICUT is called a Q label.

28:05

Anytime you want to submit style button, that is called a Q push button.

28:10

That's like a click button or a submit button.

28:14

And then the other one we're going to take a look at here.

28:16

You visibly cannot see this.

28:19

But for the design of our app, we need to use layouts.

28:24

Now, what we're going to be looking at in this first app is a vertical layout V.

28:30

And we will also be looking at a horizontal layout.

28:34

These give our app alignment.

28:37

In the case of Q V box layout, this is going to be vertical alignment.

28:43

We have just introduced a few classes that come with QT Core and QT widgets.

28:49

Remember, QT widgets provides us the GUI elements, the widgets or the objects you want to see on the screen of your app.

29:00

In QT Core, it kind of contains some miscellaneous things that we can use throughout our programs.

29:06

Mainly, for us, what we're going to be using is the QT tool for alignment, like a line left, a line right, a line center,

29:15

to help us structure our app in a more visually appealing way.

29:20

We're getting super close to starting to code.

29:23

But before we do, I've just introduced some important classes that we will be importing.

29:29

But we need to talk about a few of those important methods you're going to be using with these classes.

29:35

What is a method? Remember, it is a function in a class.

29:41

What is a property? A variable in a class?

29:45

How do we use them? A method in property must be linked to an object in order to work?

29:54

Let's take a look at some popular ones we will start off with today.

29:58

In order to add an object to our screen, we use the method add widget.

30:06

This allows us to add our object specifically to a layout, so to a column or a row.

30:13

We can change or set the text of an existing object by using the set text method.

30:22

Remember this for later, change the text of something. That's where it's really useful.

30:28

When we want to add two layouts together, we cannot use add widget because a layout is not a widget.

30:38

In order to add a column to a row, for example, we can use add layout and this adds two layouts together.

30:48

Once we have one final master layout, where everything is held, we can take that master layout and we can set that as the final layout to the main window.

31:01

Here is the method we can use to set the final design to our main window.

31:07

Our last two methods we will use throughout our course is show and hide, and this allows you to show or hide an object when something happens.

31:16

Let's take a look at your first app that we're about to put together.

31:20

This is our first application. It's rather basic, but it does everything we want it to do to hit the ground running and understand the fundamentals.

31:29

It allows us to add objects on the screen. We will be creating functions as well as programming these buttons to do something.

31:38

Let's get comfortable with the foundations of app design in piqt5.

31:45

What do we see here? I have a main window, I have a title text, I have some text for some random words, and I have clickable buttons.

31:54

Can you locate them? Here they are.

31:58

Now, I want you to think about, I introduced important classes that we will import earlier.

32:06

What classes will we need to import in order to build this app? I want you to think about that.

32:14

Well, in order to create our main window, our main window uses the class q widget.

32:23

Any text on the screen is known as a q label, 1, 2, 3, 4.

32:29

I will have 4 q label objects, and then a submit style button is known as a q push button.

32:38

You may be noticing two things.

32:41

One, everything starts with q. Yes, that's true.

32:46

Also, everything is camel-caste.

32:50

camel-casing means it's one word, but every word, the first letter, is capitalized.

32:58

That is very important if you spell one of these wrong, you're going to get an error and it's going to say undefined.

33:06

Next up, how will you design the app? How can we solve this?

33:12

What design elements should we think about here? You can pause, try and use those clues to help you.

33:18

It's not completed yet. What we couldn't do is we could start with three rows.

33:25

That's the most basic form of design in this app.

33:29

These three rows are like the base layers, and I'm going to stack them like cake in a column.

33:35

So my final design is a column.

33:38

And within that column, I have row one, two, and row three, bringing together the final application design.

33:47

How cool? Alright, let's tie everything together.

33:51

The real question we need to know to get started is what do we need in order to set up our main window screen to get our app started?

34:00

Here we are.

34:02

If you memorize any code in this first part of the lesson, memorize this because we will use this every time we start creating an app.

34:14

At the top of my code, you can see all of our imports. I'm importing QT from QT Core.

34:23

Next, I'm importing all the widgets I need to build the app from QT widgets.

34:30

Our two most important Q application, QWidget. Everything else is optional based on what you are trying to build.

34:41

After our imports, according to the code burger, we have our app settings and our app main objects.

34:50

These main objects are app and main window.

34:54

They should always be called app. This is a generic name that's used across the world by other developers.

35:01

App is equal to Q application. Q application is our class, remember the parentheses, and it also takes an empty list as an argument.

35:13

Next, I like to use the name main window. You do not need to use that.

35:18

The value of main window is QWidget that allows us to create this windowed app.

35:25

Once we have our main window object, you can go forth and you can start to style or give your app the settings.

35:34

If you want to give your app a title, you can do that with the set window title method.

35:40

That's linked to our main window.

35:43

If you want to give your app a starting size, what size will the app be when it first opens?

35:51

You can resize with a width, 300, and a height of 200.

35:57

You can choose any width and height you would like.

36:00

Soon, we will be creating all the objects that will be adding to our app.

36:04

But the last two lines in order to get our app template already to go is we need to show our main window and we need to execute our app.

36:15

Great! Let's put together our starting app and head over to VS Code.

36:20

I'll see you guys in our next video.

36:35

Alright, here we are in VS Code.

36:38

Before we jump in to start coding, let's take the code burger and let's put it in here to VS Code to give us a starting template.

37:00

What was number one again? Well, number one was we want to import our modules.

37:06

Then we have our main app objects and all of our settings.

37:14

Great! Once we have our main app objects, which should we do, we should create all app objects.

37:23

So anything we want to see in this app.

37:28

Finally, we can have all of our events, and then we want to show slash run our app.

37:36

These would be the things inside. Now, we do want to design.

37:41

Where do we want to design in our app?

37:45

Well, we want to design right here.

37:48

So all of our design can be done after we create the main object.

37:52

So I'll just say all of these design.

37:55

Alrighty, to kick things off, let's go up and let's work through and get a basic template going for the foundation of our app.

38:03

So, importing our modules.

38:05

We can say from PiQT5, that's our framework.

38:10

Now I can attach the module.

38:14

I want to go QT Core, import class.

38:19

So I want QT class from the QT Core module from the framework PiQT5.

38:27

Alrighty, now we can get our GUI going.

38:31

You can get all of the widgets we want on the screen.

38:35

So let's import those.

38:37

I like to start with the two most important ones, which are Q application and Q widget.

38:43

So right here, Q application, Q widget.

38:49

What else do we want to see in the app?

38:51

Well, I know that I want text, so we can say Q label.

38:56

I know I want some buttons, so let's say Q push button.

39:02

Finally, what type of design are we going to be doing?

39:07

Well, we're going to try to do some rows inside of a column, which we're going to actually check out here in our next lesson.

39:17

So before we do that, let's just say QV box.

39:20

That gives us one initial layout.

39:23

Now that we have everything imported, let's work on our two main objects.

39:28

So I'm going to say app equals our Q application class.

39:33

And remember that this takes an empty list as our argument.

39:38

Next up to kick things off.

39:40

Let's make a main window, and we can say here Q widget.

39:44

You can name this anything you want.

39:47

My names are going to be to help you further your understanding.

39:51

So this is my main window.

39:53

I'm going to call it my main window.

39:56

Now the other final settings we can do is we could set a title for our app.

40:03

And we could say random word maker.

40:07

And then we could set the initial size.

40:12

What size do we want the app to open with?

40:16

I could say a width of 300 at a height of 200.

40:19

Great.

40:20

Alrighty, to close things off for our start.

40:25

All we need to do is we need to take our main window

40:29

and we want to show the main window.

40:33

While the main window is showing,

40:36

we can execute or run our app.

40:41

Let's run our code and observe what happens.

40:45

There we are our starting template.

40:48

You can see that the initial size is 300 200.

40:53

But you can make it smaller and you can make it bigger.

40:57

And then you can also see the app title is random word maker,

41:01

which we gave it here.

41:03

Now this is great because every app we make will start with this.

41:07

This is the foundation.

41:09

It's like you're pouring the concrete to build the home.

41:13

So we can now build on top of this.

41:16

Now remember, there are many ways to do a certain task.

41:20

Don't be afraid to try your way.

41:23

I'm breaking this down so we understand the key fundamentals

41:28

to build apps with PICUT.

41:31

Let's head over to our next video and in that lesson

41:34

we are going to address the design of our app

41:37

and how we can do that.

41:39

I'll see you guys in the next lesson.

41:46

Welcome to our next video.

41:56

Now that we have our starting template ready to go,

41:59

it's time to design our app.

42:02

How can we use our app?

42:04

How can we use our app?

42:07

How can we use our app?

42:09

How can we use our app?

42:12

How can we use our app?

42:14

How can we use our app?

42:15

How can we achieve this look?

42:18

We have our three rows and these rows are held in one master column.

42:24

So the layout tools we'll be using are going to be our QV box layout,

42:30

V for vertical and our QH box layout or H for horizontal.

42:37

These will be used to build our rows and the columns.

42:41

How will our code look?

42:44

Well, now that we have our app ready to go,

42:48

we need to create all of the objects or widgets

42:52

that we want to store in this app.

42:55

On my screen you see 1, 2, 3, 4, 5, 6, 7 objects.

43:00

Therefore we should be creating seven different objects.

43:07

They each have their own name,

43:10

but the value can still be from the same class.

43:13

They're different objects from the same class.

43:17

My title text?

43:19

Well, that's just text.

43:21

Remember, in PiQT any time you want text,

43:25

we can say Q label.

43:28

When my app first starts,

43:31

all of these should actually be a question mark,

43:35

right?

43:36

Until we start clicking the button,

43:38

so I can create those here.

43:41

To end with, I will create three push buttons.

43:45

Each button is a different object,

43:48

but they all say, click me.

43:51

Now that we have created all these objects,

43:54

you're going to use in your app.

43:56

It's now time to design the app.

43:59

You won't be able to see any of the objects

44:02

if you were to run your code now.

44:04

It's because we can't see these objects

44:07

until we add them to our layout.

44:10

And we set that to our main window.

44:13

As I go through this course,

44:15

remember, there are many ways to solve a problem in coding.

44:19

I'm showing you one way,

44:21

and I'm breaking that down to a way

44:23

that you guys can easily understand.

44:26

If you find a different way,

44:28

or you want to try it yourself,

44:30

I encourage you to do so.

44:32

Here you can see each of those correspond to

44:35

an element on the app screen,

44:37

and that's held in our final QV box column.

44:41

Now that we created those objects,

44:44

I need to get them on my screen.

44:47

Here I have made my master layout,

44:50

which I know at the end,

44:52

everything will be added to.

44:54

But I also know that I'm going to have one, two, three rows.

44:58

So I can create three row layout objects right here.

45:05

Next up, it's time to add things to the row.

45:09

So I can start with row one,

45:11

because I know it's going to be at the top.

45:13

What do I want to do?

45:14

I want to say row one,

45:16

I want to add the title text to it.

45:19

It's going to do just that.

45:21

If I want,

45:22

I can give alignment to the text,

45:24

and I can say,

45:25

I want it to align in the center.

45:28

You can see I'm using the QT class from QT Core

45:32

that we import it.

45:33

Now that I know row one is done, check.

45:36

I can move on to row two,

45:38

and I can do the same thing.

45:39

Row two,

45:40

I want to add the widget,

45:42

text one,

45:43

which corresponds to that,

45:45

and I can also give that alignment.

45:47

Row two's done.

45:49

We can add the buttons to row three.

45:53

This is adding all of the objects you just made into each row.

45:58

Now,

45:59

if you're running your app,

46:01

no,

46:02

what do we need to do now?

46:04

What's the next step in the code burger?

46:07

Now that we have our rows,

46:09

we need to add them to our master column.

46:14

I can take that and I can say master layout,

46:17

I want to add row one.

46:20

It's important to add these rows in the order that you want to see them.

46:25

Remember, Python reads top to bottom.

46:29

We need to code like that, too.

46:31

Once we have everything in one place,

46:34

or should I say in one master layout,

46:37

I can take my main window,

46:40

and I can set the final layout to be my master layout.

46:45

If I break that down one step further,

46:48

here is what that would look like.

46:50

We're creating our master layout,

46:52

that everything eventually will be added to.

46:55

I can create three rows because that is how I'm choosing to design my project.

47:00

Then we just need to go through,

47:02

and we add each row once we've added the widgets to it,

47:07

we add each row to that master layout.

47:10

Finally, you can use set layout to set the final design of your app

47:16

to your main window, screen.

47:19

This ties together perfectly.

47:22

The codeburger, you guessed it.

47:25

You probably didn't guess it,

47:27

but it does bring in the codeburger.

47:29

I've just gone through each step individually

47:32

in how they align and how they work together.

47:35

You have a design app now,

47:37

but let's just touch on the final elements.

47:40

What is this app going to be doing?

47:42

Well, it's going to be generating a random word

47:46

and displaying that on the screen.

47:48

Every time you click a button,

47:51

how could we do that?

47:52

Pause the video, take a minute.

47:54

Just think, how could you do that?

47:57

You heard the word random,

47:59

you should have thought the random module.

48:01

I want to import the function choice from random.

48:05

Now, choice takes a list as an argument

48:08

and it randomly chooses one of the elements from that list.

48:13

So, I have a list called My Words,

48:16

and I've just put these random words in here.

48:19

I then have a function, and when this function is called,

48:22

I have a word variable.

48:24

And this choice function is going to choose one of these random words.

48:30

So word equals one of these.

48:34

I can then take my text one object,

48:38

which we already made in your app,

48:40

and I can now set the text to be that random word.

48:47

That is how I can use the set text method with our app

48:50

to set the text of an existing object on our screen.

48:55

The final question that we are going to address is event handling.

49:00

How do we connect a button?

49:02

How do we activate a button to work in our code?

49:06

What event could we possibly use in PIQT?

49:10

In PIQT to kick things off,

49:12

you're going to be focusing on one event.

49:15

Now, you can see that I have my object button,

49:18

and that is a Q push button.

49:20

That object is created here.

49:23

I then have a function, and every time this function is called,

49:26

it's just going to print this button is working.

49:29

That's all the function is doing.

49:31

I take my button objects,

49:34

and I say when the button is clicked,

49:36

we want to run the test function.

49:40

Click, that's the event type in PIQT.

49:44

Let me translate this now.

49:47

The event with literally translate to when this button is clicked,

49:52

I want to connect to this function.

49:56

That is how we handle events in PIQT.

50:00

In our first app, we are just going to be looking at the click event,

50:03

but in other projects that we do in this course,

50:06

we will be learning about other events as well.

50:10

All right, let's head over to VS Code,

50:12

and let's finish off our app.

50:14

I'll see you guys in the next video.

50:36

Here we are in our next video.

50:44

In the lesson, we introduced how we can create a layout

50:49

in design our app the way we want it to.

50:52

We also addressed how to get the objects to appear on our screens,

50:57

because we now know that after we create an object,

51:01

we then need to add it to our design.

51:05

Let's start off by creating all the app objects that we need.

51:09

First up, I'm going to create a title,

51:12

because I know I'm going to have a title that is going to be text on the screen.

51:16

According to my app, I can just put random keywords,

51:20

because that's what I want the title to be.

51:24

I will then have three different text.

51:28

So as long as they all have a different name,

51:32

because they're all different objects, that's fine,

51:35

and they can still all use the same class.

51:39

Initially, when the app starts,

51:42

I want my text to be a question mark.

51:46

When we click a button, this is going to change to a random word.

51:53

Great, we have our text objects.

51:56

What other objects do we want?

51:59

The buttons, so for each button, you should create a Q push button.

52:06

The Q push button, that can say click me.

52:10

We need to give them different names. Great.

52:14

We now have our seven objects, all of these we want to see on our screen.

52:19

Now that we've created these objects,

52:21

it's now time to move into our design.

52:24

We got to get these onto our layouts onto our screen.

52:28

The first thing we can do for our design is let's create all the layouts we want.

52:34

Now, I know that my final layout, my master layout,

52:38

I want everything to be held in a column.

52:41

So I'm going to make that.

52:43

Within this master layout column, I know I'm going to stack some rows.

52:48

It's going to be like cake.

52:49

So I want to have row one, row two, row three.

52:53

In order to get that, I need my Q H box layout.

52:57

Therefore, let's go up and let's just add that onto our imports.

53:02

Let's say Q H box layout.

53:05

Now that we have that, I can go forth and I can say, okay,

53:08

I am going to make a row one.

53:11

Let's make a row two and row three.

53:13

These are the designs in the app.

53:16

Great.

53:18

We can start to add our objects.

53:21

How do we add these widgets to our screen?

53:24

Well, do you remember the method we learned?

53:27

Add widget.

53:29

What is that going to be linked to?

53:32

Well, let's say, hey, Python.

53:36

In row one, I would like to add my title to the screen.

53:42

I would like my title to have the alignment of the center of the screen.

53:49

So I can pop that in just like so.

53:53

That's what that translates to.

53:55

Row one, I would like to add my title.

53:58

My title is a widget Q label.

54:02

And then my row is the layout.

54:05

Great.

54:06

That's row one.

54:08

I can move on to row two.

54:10

In row two, we are going to have more.

54:12

I'm going to have text one.

54:14

Text one is going to have its alignment again.

54:17

And I can say once again, a line center.

54:20

But row two is also going to have our other two texts.

54:25

So I can say text two, text three.

54:29

Remembering that Python reads like a book.

54:32

Left to right top to bottom.

54:35

So the order we add these to our rows,

54:39

it's going to go left to right.

54:41

Text one, text two, text three.

54:44

That concludes with the final of adding our buttons to the screen.

54:49

Our buttons do not need alignment.

54:53

So I can just take it and we can just add the button.

54:57

How it is.

54:58

Button two, button three.

55:00

Awesome.

55:01

Look at our design.

55:03

Okay.

55:04

If any of that is confusing, go back through some of our slides.

55:08

We watched the last two minutes of this video.

55:11

Right?

55:12

We create our layouts and we simply just go in order.

55:16

All right.

55:17

I've made my layout.

55:18

I'll just start with row one.

55:19

We do what we need to do.

55:21

row two and row three.

55:24

Now that we have all these rows,

55:26

I just want to drop them into my master layout.

55:31

Here's us using the ad layout method.

55:34

Now remember that we use the ad layout method because a row in this example is not a widget.

55:44

It's a layout.

55:45

If we want to add rows or columns together, we need to use ad layout.

55:51

So how we could translate this is master layout.

55:54

We want to add row one at the top.

55:59

Master layout.

56:00

I would like to add row two under row one.

56:04

And then master layout.

56:06

We can add row three under row two.

56:12

Now that everything is stacked in our master layout, let's just say, okay.

56:17

I have my final design ready to go.

56:20

Main window.

56:21

I want to set the final layout to be my master layout.

56:27

Incredible.

56:29

Let's give our code a run.

56:32

There we are.

56:34

You can see our app.

56:35

I have the title, which we've given it right here.

56:39

I have my three question marks ready to go for my random words.

56:43

And then we have all the buttons we added.

56:46

Now if you try the buttons, we have not connected any events yet.

56:50

That's what's yet to come.

56:53

In the next video, we will implement our random words as well as the events for each button.

57:00

I'll see you guys in the next video.

57:09

All righty.

57:24

Welcome back.

57:29

Let's get this app finished.

57:31

Now we need to introduce random words and link our buttons with our events.

57:38

First things first.

57:40

Let's create some random words.

57:43

So when you hear the word random, you should immediately be thinking of the Python random module.

57:50

If you're not familiar with this, do a little reading on the documentation.

57:55

It's one of the built-in Python modules like random or time or math.

58:02

Python has these modules.

58:04

And choice is going to allow us to choose a random word from a list.

58:10

Speaking of lists, let's go down here with all of our objects and let's make one.

58:15

Let's just say in my words equals a list.

58:18

I've already prepared some words.

58:20

You guys be creative.

58:22

Choose a hobby that you're passionate about and use those words here.

58:26

All righty.

58:27

So let's see.

58:28

Let me mark these.

58:29

We've imported choice.

58:31

We have a list of words.

58:33

We're now ready to make some functions.

58:37

I'm going to add one additional content.

58:40

Add functions.

58:42

I like to create my functions down here in the box.

58:47

Okay.

58:48

After our design, after the design elements of our app,

58:52

there are many ways to do this again.

58:54

And if you think of a different way, go with your way, try your way.

58:59

The way I'm about to do it is to make it more readable for you.

59:03

And easier to understand in the big picture of things.

59:06

It doesn't matter if you do the same problem in three lines of code or 15 lines of code.

59:11

Were you able to solve the problem?

59:13

If the answer is yes.

59:15

Awesome.

59:16

That's great.

59:17

And you should be proud of that.

59:19

Let's make a function.

59:21

Now, to be exact, I'm actually going to make three functions.

59:24

They're all going to be the same thing.

59:26

But they're going to be linked to different events.

59:30

So random word.

59:32

When I call this function,

59:35

I would like to get a random word from my list of words.

59:41

So I'm going to use the choice function here.

59:44

And I'm going to insert my list.

59:46

So now word is going to be one of the random words from my list.

59:50

It could be hello, goodbye, test app, any of those.

59:55

I can then take my object text one.

01:00:00

Remember, we created three of these, one, two, three.

01:00:05

Currently, text one is a question mark.

01:00:08

I want to update that value or change that value.

01:00:13

Who remembers what method do we use to change the value of an existing object?

01:00:19

Set text.

01:00:22

So I can link set text method because I want to change the value of text one.

01:00:28

And what do I want the text to be?

01:00:30

Whatever random word was chosen.

01:00:32

That's what we want.

01:00:34

Great.

01:00:35

I'm going to use this now a few times.

01:00:38

So let's just take this.

01:00:40

What do we need to change?

01:00:42

Well, random word two.

01:00:45

We now want to change text two.

01:00:47

And then random three would like to change text three.

01:00:52

Great.

01:00:53

We have our three functions.

01:00:55

One, two, and three.

01:00:57

To close things off, we need our PICUT events.

01:01:02

And remember, we have just learned our first event of clicked.

01:01:07

Clicked is linked to a button object.

01:01:10

So let's say button one.

01:01:12

When button one is clicked.

01:01:16

I want to connect with my random word.

01:01:20

One function.

01:01:24

When my button two is clicked.

01:01:27

I want to connect with my random word two.

01:01:32

And I'm just going to take that for the last one.

01:01:35

And we can say button three and random word three.

01:01:39

Great.

01:01:41

Run your apps.

01:01:43

Play with your apps.

01:01:44

Experiment and review our code.

01:01:46

What did we just do?

01:01:48

Save this code somewhere as it's going to help you build our future projects.

01:01:54

It is the code burger structure.

01:01:57

It's what we're going to be using in this course.

01:01:59

I'm going to give my app a run.

01:02:02

There we are.

01:02:03

Click.

01:02:04

Ah, look at that.

01:02:06

All different.

01:02:07

That's great.

01:02:08

We have it working exactly how we wanted it to.

01:02:11

Very well done.

01:02:12

We have put together our first app.

01:02:15

But fear not because what we've learned here we are going to use in the remaining projects of this course.

01:02:22

I'll see you guys in the next lesson where we're going to introduce our next project.

01:02:45

Welcome back to our next project.

01:02:55

In this project, you're going to be putting your knowledge of QT widgets to the test as we build an interactive calculator with PICUT.

01:03:05

Before we dive into this project, let's take a look at the famous code burger one more time.

01:03:12

Remember the structure of what we're trying to do here.

01:03:16

We will use this structure within this project as well.

01:03:20

Remembering all of our imports, our main app objects with the settings.

01:03:26

Once we have those two, feel free to create all the widgets you want to see in your app.

01:03:33

Once you have those, we can then design the app with our layouts and set that to our main window.

01:03:41

When everything is set, it's time to run and execute your app.

01:03:45

This is the code burger.

01:03:47

So in the past, we have been using QVBox layout in QHBox layout.

01:03:56

And remember that V is for vertical for a column and H is for horizontal and row.

01:04:05

You've got some practice with these in the last project.

01:04:10

Looking at this calculator app, how would you design this?

01:04:15

Do you see rows and columns? Does that make sense?

01:04:19

What other options do we have?

01:04:22

Well, what I see is a grid.

01:04:26

What if there was a way to create a grid for us?

01:04:30

There is.

01:04:31

With PICUT, we have a layout called QGrid Layout.

01:04:36

And you can see that I have my object grid in the value is QGrid Layout.

01:04:40

Which I'm going to use instead of creating four columns in five rows.

01:04:47

That seems really repetitive.

01:04:49

I can create one grid and add things to my grid, which becomes incredibly useful for us.

01:04:58

But how do we add things to this grid?

01:05:01

Do we still use add widget?

01:05:04

Yes, we are adding an object to a layout.

01:05:08

We still will use add widget.

01:05:12

But now add widget actually takes two additional arguments.

01:05:18

We create our grid objects.

01:05:21

Then we say grid, we want to add a button where we need to specify the row in the column.

01:05:31

If we translate this, layout add this object to this row in this column.

01:05:39

Now, for this to work, we do need to create some type of index or current position.

01:05:46

In this example, I've said row equals two in column equals one.

01:05:51

That would actually give us the number five button.

01:05:56

If you're thinking how that doesn't make sense, remember programming languages start on zero.

01:06:04

So I'm actually saying row zero one two column zero one that gives us number five.

01:06:16

We are trying to take our knowledge from an idea all the way to a completed application.

01:06:24

Currently, we are on number one.

01:06:27

You know how to get to number two.

01:06:30

And after the last two slides, you should have a rough idea on how we can achieve number three.

01:06:37

You do see a new object in our calculator.

01:06:41

This little guy is called a queue line edit tool.

01:06:46

And this is where we will see all of our expressions being entered and evaluated.

01:06:53

Number four is like a final bonus redesign.

01:06:56

And it's a way for us to add slightly more details to our app.

01:07:01

We can change the font, change the color, things like that.

01:07:05

That's our goal for this app to go from design one all the way to design three.

01:07:11

If we can get here, this is a completed product.

01:07:14

We can then worry about getting to number four.

01:07:18

Looking at this calculator now.

01:07:21

This whole grid system it seems like it's going to take a while because I have,

01:07:26

I think at least 17 buttons, maybe 18 buttons.

01:07:31

So it seems really repetitive.

01:07:33

How can we deal with repetitiveness in coding?

01:07:38

What do we have for this?

01:07:40

Loops.

01:07:42

What are the two types of loops you know in Python?

01:07:46

The while loop and the for loop.

01:07:48

The for loop is used to iterate to go through something else.

01:07:55

Let me propose that we actually loop through to create our grid.

01:08:04

So let me break that down to plain English in general tasks before you see any code.

01:08:12

I'm making a for loop and I'm going to go through this list.

01:08:17

This list will be all the string elements that I want my buttons to say.

01:08:25

What do I want to see on my buttons?

01:08:28

Like the letter C, the less than sign the number four.

01:08:33

All of those I could add to a list.

01:08:36

And I could loop through and say for every button text in my list.

01:08:43

Every time I loop through one I want to create a new push button object with the current text I'm on.

01:08:53

Two, for that object I will create an event only for that button.

01:08:59

Great.

01:09:00

Then I want to add this new button to my grid layout.

01:09:05

One, two, and three all work for one button.

01:09:10

Number four, before I make the next button I should change my row and or change my column.

01:09:19

So think about this.

01:09:21

How can you achieve this and how can you achieve this with using a for loop as well as counter variables?

01:09:29

If you're up for a little challenge pause the video here.

01:09:32

Give it a try and then come back to continue watching.

01:09:36

Putting this into code on the outside of my for loop I have two counter variables responsible for keeping track of my row in column.

01:09:45

I'm going through my list of buttons and every time I'm creating a new button object.

01:09:52

A new event for that button.

01:09:55

And then I am adding, I'm taking my button and we're adding it to our button grid.

01:10:04

Every button is being added at an index a position row column.

01:10:10

Once we add one button I want to increase my column or change my column.

01:10:18

If I get to four columns then I want to reset my columns and I want to go down to the next row.

01:10:29

This remember we start on zero so it's actually zero one two three.

01:10:37

Increase row zero one two three and I'm repeating myself amazing very well done.

01:10:48

I would love it if you took the knowledge that we just learned in this lesson and you go on and you create your design and create the initial product for our app.

01:10:58

I'll see you guys over in VS code where we are going to put all of our knowledge to the test.

01:11:29

Welcome to our next video.

01:11:33

In this video we are going to put together our initial design here in VS code for our calculator app.

01:11:39

Let's get started.

01:11:41

So who remembers the code burger?

01:11:44

Let's go through those steps.

01:11:46

What will we need in order to complete this project?

01:11:49

Well, we really just need some widgets.

01:11:52

Okay, so I'm going to say from piQt5.Qt widgets.

01:11:57

Let's import the two most important ones.

01:12:01

So Q application.

01:12:04

Q widget.

01:12:06

What else will we need to create this?

01:12:09

Well, we need our new tool, our Q line edit.

01:12:13

We will be using push buttons.

01:12:16

Then our layouts.

01:12:18

We have our QH, which we can use for row if we need it.

01:12:23

We have our QV box for columns.

01:12:29

And our new tool is our Q grid layout, which I can import up top like so.

01:12:37

Looking good.

01:12:39

Alrighty.

01:12:40

Now that we have those, we can create our starting template.

01:12:45

So our app, which is our Q application, then we can say our main window.

01:12:58

Amazing.

01:12:59

Who remembers how to give the main window error title?

01:13:02

Let's say main window dot set window title.

01:13:05

Here I can put Calculator app.

01:13:09

Then we can take our main window and we can resize.

01:13:13

So the initial resize, let's say the width can be 250.

01:13:18

And the height can be 300.

01:13:21

We can see how that plays out when we run out.

01:13:25

App.

01:13:26

Let's put in the final two lines.

01:13:28

What do we need to show our starting template?

01:13:31

Well, heading down here, our final two lines.

01:13:34

We can show our main window.

01:13:39

And we can secure our app.

01:13:43

Great.

01:13:44

Let's give it a run.

01:13:45

Alrighty.

01:13:46

There we are.

01:13:47

Our starting template.

01:13:49

What do we need on here?

01:13:50

We need to now design the layout using our Q grid box.

01:13:54

Our Q line edit and then our push buttons that we want for our clear and delete.

01:14:01

As a starting template.

01:14:04

So this is what we're aiming for.

01:14:07

Alright.

01:14:08

And I'll bring this back up as we work through this project.

01:14:11

But this is the goal.

01:14:12

Up top in a column.

01:14:14

We have a Q line edit.

01:14:17

This is like where I enter something.

01:14:19

Then we have our Q grid layout.

01:14:21

We're at all of our buttons.

01:14:23

And the last one could be a row here that I may put.

01:14:27

And that contains our final two Q push buttons.

01:14:30

So to get our row in our design.

01:14:35

Well, let's create all of our objects first.

01:14:38

So even before my design.

01:14:41

Let's go back and let's say something like all objects or widgets.

01:14:47

Alright?

01:14:48

Because that's what they are.

01:14:49

What do we need here?

01:14:50

Well, I need a place for my input.

01:14:52

So let's say like a text box because that's what it can be.

01:14:56

This is our Q line edit.

01:14:58

Now, Q line edit does not take anything.

01:15:01

I will make my grid which is a layout.

01:15:04

So Q grid layout.

01:15:07

Now, the way we looked at this in the lesson is we have a for loop that can go through a list

01:15:15

and every element in that list or every position.

01:15:19

It can append or put that into our grid layout.

01:15:24

So I need a list of buttons.

01:15:27

Now, what order do they need to go in?

01:15:30

And we need to think about that.

01:15:32

Let me bring up our example of the app again.

01:15:35

I'm going to loop through.

01:15:37

So either we want to do it in columns 740

01:15:42

or I could do 789 slash 456 star.

01:15:48

Let's go with the rows.

01:15:50

So how about we start by making this?

01:15:53

I could probably keep this up as a template.

01:15:56

So let's say 789 slash, right?

01:16:06

And then I'm coming down the row.

01:16:08

We have four, five, six.

01:16:13

Let me enter the rest of these here.

01:16:15

There is our list of button text.

01:16:19

Now, this makes it really difficult to see.

01:16:22

So let me refactor this.

01:16:25

And I'm just going to make it look more pretty

01:16:27

so that it's how it would appear on the calculator.

01:16:31

So there is the same list.

01:16:33

I've just put it in rows now.

01:16:35

And this is essentially what we want to see on our app screen.

01:16:40

Right?

01:16:41

When the app fires up, it appears and you can see how each row of this list

01:16:47

is corresponding to the row in our calculator.

01:16:51

Now, I just made this look like the calculator will

01:16:54

but one long list is the same.

01:16:57

This is easier to understand in interpret.

01:17:00

Now, the final two buttons we can make outside of our list

01:17:04

and those can be our push buttons.

01:17:07

Let me close the app.

01:17:09

Let's create a clear button and this will

01:17:13

delete everything in the box.

01:17:15

I'll put C.

01:17:16

And then we'll say delete and delete could be a push button

01:17:19

like we could do that for delete.

01:17:22

We could also right clear and delete.

01:17:24

That might be fine.

01:17:26

Clear?

01:17:27

Let's keep this simple for delete.

01:17:30

Alrighty.

01:17:31

So we have everything that we want to see on our screen at this point.

01:17:35

Let's go through and let's map this out and get our design.

01:17:39

We have our objects.

01:17:41

We need our design to start flowing.

01:17:44

How could we get our design started here?

01:17:46

Well, let's create our layouts.

01:17:48

So I'm going to say master layout.

01:17:51

I know in the end everything will be held in a column.

01:17:54

That makes sense.

01:17:56

At the top of my column, I would like my text box.

01:18:02

Right?

01:18:03

That input.

01:18:05

So I'm going to put that right there.

01:18:07

Directly under this.

01:18:09

I would like to actually add my grid of buttons,

01:18:14

which I don't quite have those yet.

01:18:17

So I'm thinking out loud here.

01:18:19

Then at the bottom we want to have, I actually want to have a row.

01:18:23

So let's also say add layout and let's say button row.

01:18:29

While I'm here, let's create that button row.

01:18:34

So I'll say button row.

01:18:39

And within that button row, I would like to add my widgets.

01:18:43

So from left to right, let's say the clear button.

01:18:46

And then we have the delete button.

01:18:50

Let's focus on our grid.

01:18:52

We have everything going.

01:18:53

And so we can see that.

01:18:54

Let me turn off the grid.

01:18:56

Let's set the master layout to the main window.

01:18:59

Because that's our final design.

01:19:02

I'm going to run my program.

01:19:04

This is what it looks like currently.

01:19:06

We have that box to top.

01:19:07

We want we have clear and delete.

01:19:09

I want to get the buttons between those two now.

01:19:13

So here is where I'm about to implement that loop.

01:19:17

And remember, every time we loop over, we are creating a new object with a new event.

01:19:24

While also increasing the row and the column as well.

01:19:28

I'm going to shut the app down, trash the terminal.

01:19:31

We are going to go right here before our design.

01:19:35

This looks like a good place.

01:19:37

Before our design, this is where our for loop is going to take form.

01:19:41

Now, I'm going to create my two counters.

01:19:43

So row in column.

01:19:45

And this will keep track of how many buttons are in each row as well as each column.

01:19:51

I can say for every text in this list.

01:19:56

So I have my list of buttons.

01:19:58

And I want to say for every string for every text in here.

01:20:03

So let's say for every text in my list of buttons.

01:20:10

I want to create an object for the current button I'm on.

01:20:14

So I'll say button equals Q push button.

01:20:18

What do we want it to say?

01:20:20

Well, I wanted to say whatever the current text is in the loop.

01:20:25

When this loop first takes off, text is going to be the number seven.

01:20:31

Number seven will be the text value of the first push button we create.

01:20:38

For this button, it has the object name button.

01:20:42

I can create my event.

01:20:45

And I'm going to say I want to connect it to some type of function,

01:20:49

which actually I don't have yet.

01:20:52

Okay, so let's keep that empty.

01:20:54

While we have our button created, we have the event created,

01:20:59

which I could say none.

01:21:01

While it's also none, let's turn it off.

01:21:03

We can now add this to our grid.

01:21:06

Let's take our grid.

01:21:08

Let's add the widget.

01:21:10

What widget do you want to add?

01:21:12

I want to add the current button at the current row at the current column.

01:21:18

Looking great.

01:21:20

Alrighty.

01:21:21

Before we go on any further, I now need to increase the column.

01:21:26

I want to move to the next button on the right.

01:21:30

So column plus equals one.

01:21:33

If my column is greater than three,

01:21:38

I want to reset my column.

01:21:41

So column now equals zero.

01:21:44

And I can increase my row because it's time for a new row.

01:21:50

This puts together exactly what we want to see in our calculator app.

01:21:53

The final step is let's just turn this back on again.

01:21:57

We can add our grid to our master layout design.

01:22:02

When we give the app a run, we should see our basic template with all of our buttons.

01:22:08

Looking great.

01:22:09

This is the basic form of the app.

01:22:12

Now notice it doesn't do anything yet,

01:22:15

but we have everything ready to go for adding our functionality.

01:22:19

I'll see you guys in the next lesson where we're going to discuss how we can add functionality to our app.

01:22:32

Great.

01:22:35

Now we have our design for our calculator app completed.

01:22:56

But what's the problem?

01:22:58

It doesn't do anything yet.

01:23:00

It's fine.

01:23:01

Because adding the functionality to our applications comes after we create our initial design.

01:23:09

So in this lesson, we are going to learn how to create that functionality,

01:23:13

as well as learning how to evaluate our expressions.

01:23:17

For example, 2 plus 2, evaluate 2, 4.

01:23:23

In order to do this, we could do this a few ways.

01:23:27

Now what are you thinking about right now in this moment?

01:23:31

How would you add functionality to our app?

01:23:35

You may be thinking a few things and that's okay.

01:23:38

Before watching this lesson, you may want to try and implement your own ideas in the logic,

01:23:43

which I highly encourage you to try.

01:23:46

I'm going to show you one of the many ways to solve this.

01:23:49

In the way I'm going to show you is actually done through one sole function.

01:23:55

I am creating one function called button click.

01:24:00

This is the only function that's actually required to run our app.

01:24:05

You could make a function for each button, sure.

01:24:08

That's just a lot of code, but would that work?

01:24:11

Absolutely, it would work.

01:24:13

What we're doing is going down, we are checking if the text of the button is the equal sign.

01:24:21

If it is, then we set the value of this variable to be the equal sign.

01:24:30

If I press the button that has the letter C on it,

01:24:35

I would like to clear my Q line edit object.

01:24:41

If we press the less than button, we would like to cut the last element of our current text.

01:24:50

Do you know how to solve any of these currently?

01:24:54

Well, let's take a look at some of them.

01:24:57

Our first one, let's begin with this.

01:24:59

So when we click a button, I want to get the text value off of that button object.

01:25:07

Do you remember how we can do this?

01:25:10

Well, we can use the text method.

01:25:15

And this method is linked to an object, and it gets the text value of that object, which is pretty cool.

01:25:23

You can see here that I'm getting the text value of the button.

01:25:27

I'm getting the text value of the input box, the Q line edit box.

01:25:33

And I'm doing that here, here, and here, pretty cool.

01:25:40

All right, now that we've collected the text from the button,

01:25:45

we need to evaluate the expression that we enter into the input field.

01:25:52

For example, if you clicked 3 plus 5, we need to now evaluate that.

01:26:00

We want to change that 15.

01:26:03

Any thoughts on how we can do this in Python?

01:26:06

Well, in fact, you may have seen this Python function around before.

01:26:11

Python has a function called Eval.

01:26:15

This function is made to evaluate expressions.

01:26:19

So if the expression is true, if the expression is allowed, it's going to run.

01:26:27

Next, if we press C, we want to clear the input field.

01:26:34

How can we do that? Well, thanks to PiQT, PiQT has a method called clear.

01:26:40

We can link clear to any object that we want to simply put clear.

01:26:46

Great. This brings us to our final one.

01:26:50

If we press the delete button, we want to delete the last item that we entered.

01:26:55

Any thoughts on how we can cut an element from a string.

01:27:00

You should know this from working with strings and string manipulation, as well as working with lists.

01:27:07

In order to cut, I have a variable called current text.

01:27:12

And that is the text value of whatever is in my input field.

01:27:17

So I'm going to take that text and I'm going to cut using our square brackets to index the last position of the string minus 1.

01:27:29

This is a key fundamental of string manipulation that you should already feel relatively comfortable with.

01:27:39

This takes us to our last method.

01:27:42

Now, a current problem we actually have is all the buttons have the same event or the same target of event.

01:27:50

And we need a way to tell them apart.

01:27:53

But don't worry, because PiQT has actually got us covered for this as well.

01:27:59

We only need to do this if we are making one function for our entire application.

01:28:05

Which in this lesson, that's what I'm doing.

01:28:08

We can use the sender method.

01:28:11

And I'm going to link sender with our app object.

01:28:17

The sender method was created specifically to tell the difference between multiple events in PiQT.

01:28:25

So that's the first thing we do.

01:28:27

I created a variable called button.

01:28:29

And I am tracking which button did I click?

01:28:32

Which button sent the event to me?

01:28:37

Amazing.

01:28:38

The last thing we can do here is I'm going to throw in a try statement because I could potentially get an error.

01:28:45

I would like to try to evaluate the expression.

01:28:50

If that's not possible, then I just want to set the text of the input to error.

01:28:56

Why is this useful?

01:28:59

Why would this happen?

01:29:00

Well, if you pull out your iPhone right now, any phone you have.

01:29:04

And you pick any number.

01:29:05

And you say, I don't know, 20 divided by 5.

01:29:08

You're going to get 4.

01:29:11

But if you say 20 divided by 0, you're going to get error.

01:29:17

That is what could happen.

01:29:19

What if the user tries to divide by 0?

01:29:23

We want to anticipate what could the user do wrong?

01:29:27

And I'm going to catch that right here.

01:29:29

So as a final precaution, I am going to add my try and accept statement to catch any potential errors.

01:29:38

Amazing.

01:29:40

Before heading back into the S code to implement our app functionality, you are going to see the next few videos.

01:29:47

In the next video, we will finalize our app.

01:29:50

Then I have prepared two remaster challenges for you that we should be getting comfortable with.

01:29:57

Here are your two challenges for this project.

01:30:01

Once you have a working product, your first challenge is to remaster your app into a class-based application.

01:30:11

So I want you to try to build your own class and refactor all your code to get it in your own class.

01:30:20

All right?

01:30:21

If you're able to do that, why don't you try to add some designs and styles to your app?

01:30:28

As a hint, you can check out the Q font module from PiQT.

01:30:32

This will allow you to play with your fonts.

01:30:36

And for all the styling, check out the method set style sheet.

01:30:41

If you have ever worked with CSS, you're going to be ahead of the game.

01:30:45

Because we can add CSS to our apps.

01:30:49

I'll see you guys over in VS Code, where we are about to finish our calculator app.

01:30:58

We're going to do the same thing.

01:31:20

Amazing. Now we've addressed the functionality that we will be adding to our application.

01:31:26

Here is where we left off.

01:31:28

I've cleaned some things up a little bit as we're getting ready to add in our function.

01:31:32

The question becomes, where should this go?

01:31:36

So if I take away all of our spacing here, based on our last app, we put the function at the end.

01:31:43

But I am going to get an issue because right here, we need to connect to some button in order to create this event.

01:31:52

So it has to go before our point here, because this needs to go before our layout.

01:32:01

Our function can rest just up here.

01:32:05

Right after we create all the elements, we'll use all those widgets.

01:32:09

I'm going to create my function.

01:32:11

And this function is going to be responsible for any time of button is clicked.

01:32:16

So remember, we have all those buttons on the screen.

01:32:20

And each button really has the same function call.

01:32:26

So we need to check what is the face value of that button.

01:32:31

What text is currently on the button?

01:32:34

What we can do is I can create a variable and I'm going to listen to who sent the message.

01:32:41

Who was clicked? That's what it's listening for.

01:32:45

Then I can take that button of who was clicked.

01:32:49

And I can take the text value of it.

01:32:53

So those two are working together right there.

01:32:56

First, I'm listening to what button was clicked.

01:33:00

Then based on that button, I'm getting the text value from it.

01:33:04

We can then check if that text value is actually the equal side.

01:33:10

If it is, then we want to get the text that is within our object text box.

01:33:18

Let's get that.

01:33:20

We can then try to evaluate.

01:33:23

So remember that this is an expression.

01:33:25

And I'm going to have a result.

01:33:27

In this result, we want to evaluate the equation.

01:33:31

So like 2 plus 2, my result should equal 4.

01:33:35

I can set my text box as the updated value of whatever my result was,

01:33:43

making sure that I convert that to a string.

01:33:46

What does every try statement need?

01:33:48

Well, every try statement, we want to have an accept.

01:33:51

We want to catch that.

01:33:52

So how can I catch that for every exception?

01:33:56

I don't just want to say accept.

01:33:58

I want to say exceptions overall and I can give them a nickname.

01:34:03

And I'm just going to refer to them as E.

01:34:07

E means every exception.

01:34:10

So I can just print off and I'm just going to say error.

01:34:13

Let's put two dots and I'm going to say E.

01:34:15

So then I can get that type of error as well.

01:34:18

If we press the equal sign, we evaluate that expression.

01:34:22

Let's check if the original button text is actually clear.

01:34:28

Right?

01:34:29

Does the text value say clear?

01:34:31

If it does, we can take our text box and we just want to clear the value that's within it.

01:34:38

That's where the piqt handy clear method comes in.

01:34:42

What is the last button that needs its own as well?

01:34:46

Well, our delete button.

01:34:49

Right?

01:34:50

If we press delete, we would like to be able to backspace.

01:34:56

So if the face value of our button is that sign that we set,

01:35:02

we can then try and do a few things.

01:35:05

We would like to get the current text within our text box.

01:35:11

Whatever it is, it could be 85-2.

01:35:14

I want to get 85-2.

01:35:17

I want that value.

01:35:18

It could be 100.

01:35:19

I want to get 100 from there.

01:35:22

So let's say current value.

01:35:26

It's the current value within that box.

01:35:28

And that is equal to my text box, the text within.

01:35:32

Looking good.

01:35:34

In order to update this now, every time I click,

01:35:38

I want to update the text box.

01:35:41

So I can say set text because I want to change the current value of that.

01:35:46

And I want it to be the current value, but I want to take off the last position.

01:35:52

So I can do that by signaling this as the index.

01:35:56

Great.

01:35:57

And to touch up, I want one more, but it's going to trigger no matter what.

01:36:01

So if I put an else here, now that we understand that each of these are a condition,

01:36:08

we also need to understand that I can only press one button at one time.

01:36:13

All of these are a part of one condition.

01:36:17

Instead of saying, if, let's say, also if, or eliff,

01:36:22

our final else, we can say the current value,

01:36:27

is going to be the text box value.

01:36:29

And let's just say our text box, set text, our current value, plus text.

01:36:37

Now, remember, text is going to be a button value.

01:36:40

So if it's not an equal sign, if it's not the clear button, if it's not the delete button,

01:36:47

then it's going to be a number or an addition symbol, a subtraction symbol.

01:36:54

We want those to appear in the text box.

01:36:57

That is what this else is doing.

01:36:59

This is adding numbers to the text box as we click them.

01:37:03

This is our overall function and the functionality to it.

01:37:07

We just need to connect our buttons to this function and we have a working app.

01:37:14

Going down now, let's take away all this space.

01:37:18

We can turn back on this event and I'm going to put in here the name of our function,

01:37:24

which is button click.

01:37:26

At the bottom here, right before we execute our app,

01:37:31

let's take the clear button that we made.

01:37:34

Let's say when that's clicked, I want to connect also to button click.

01:37:38

And when the delete button is clicked, that can also connect to our function.

01:37:45

But in clicked, looking great, amazing.

01:37:50

All within 80 lines of code, just about.

01:37:54

We have a working calculator app.

01:37:57

Well, let's check that it's working.

01:37:59

That was our final stage of the basic form of this app.

01:38:03

All right, let's go down here, let's say 55 times 62 equals.

01:38:10

Wow, there we go.

01:38:12

Looking good.

01:38:14

Minus 36 equals.

01:38:16

Great.

01:38:17

Clear?

01:38:18

That works.

01:38:19

Two's.

01:38:20

We can delete.

01:38:22

Amazing.

01:38:23

Well done.

01:38:24

Coming from the first warm-up app that we created,

01:38:28

you were introduced to these basic concepts of design

01:38:32

and how we set up a template app in PiQT.

01:38:36

This is your first real-world application in your first project,

01:38:40

this calculator app.

01:38:42

Very nicely done.

01:38:43

What we've learned here, we're going to continue to build on.

01:38:46

In the next video, we are going to learn how to re-factor this code

01:38:50

as a class-based application.

01:38:52

I'll see you guys in the next lesson.

01:39:02

As we enter this lesson, let's address what we did in the last lesson.

01:39:24

We completed the basic functionality of our calculator app,

01:39:29

a fully working app in Pithon with PiQT using this framework.

01:39:34

Now, in this video, we are going to learn how to re-factor our code

01:39:39

into a class-based application.

01:39:42

Why is this so important?

01:39:44

Well, PiQT is already structured in classes.

01:39:48

As you can see here with QT widgets, it's everything we already have.

01:39:53

So, you should feel confident and comfortable creating your own classes, methods, and properties.

01:40:01

The second point is, as we go forward in our projects,

01:40:05

they are going to become more class-based focused.

01:40:09

As this course is designed to take your basic programming skills of Pithon,

01:40:15

an object-oriented programming, and grow on that idea,

01:40:20

that concept of OOP, or object-oriented programming.

01:40:25

As I've introduced how this framework is class-based,

01:40:29

it's now time to start making our projects in a class.

01:40:34

Right here is where we left off in our last video.

01:40:37

Our app still functions.

01:40:39

I haven't added any more code.

01:40:41

It's now time to re-factor.

01:40:43

We looked at this very briefly in the introduction lessons of this course.

01:40:48

But, if there's anything that your hesitant about,

01:40:51

feel free to check out my other object-oriented programming course,

01:40:55

or just go back a few slides and review what we looked at.

01:40:59

In order to do this, let's create some space here.

01:41:02

So, pretty much everything I want to have in a class.

01:41:08

And the last two things, I'm actually going to remove our app and main window,

01:41:13

because those will automatically run here at the end.

01:41:17

So, I'm just going to store them down here for now.

01:41:20

Going up to our top, let's try and keep everything.

01:41:23

So, I'm going to create a class, and I can call this Cal app.

01:41:27

That's my Calculator app.

01:41:30

Everything below, we pretty much want inside of this class.

01:41:37

All right.

01:41:40

I am now storing all of our original code in a place called class app.

01:41:46

Now, we still need a main window.

01:41:50

And as you saw, I just removed my main window.

01:41:54

So, how can I pass in a main window that my class can use?

01:41:59

Well, the obvious one that we may be thinking is,

01:42:02

why did you just remove that?

01:42:05

Well, what I can do is, I don't actually want to do this.

01:42:09

I can take first off, let's uppercase that.

01:42:12

I can take Q widget, and I'm actually going to inherit Q widget.

01:42:16

Why can I do this?

01:42:18

Well, remember, in PICUT, all of these are classes.

01:42:23

So, a class can inherit a class.

01:42:26

I'm using this Q widget as a super class.

01:42:30

Can now take that away.

01:42:32

I'm inheriting that.

01:42:33

I'm left with all of our starting code, and this code starts as soon as the app starts.

01:42:40

So, what is that special constructor method that automatically runs when an object is called?

01:42:47

In it, we need our initializer function.

01:42:51

So, let's say, in it, I'm going to put self.

01:42:54

I'm going to activate my super class.

01:42:57

So, with our super function, we can initialize the super class.

01:43:03

Now that we have that, let's take all of this.

01:43:06

We're just going to put that right there inside.

01:43:08

Main window is nothing.

01:43:11

But now that I'm working with a class, these are not variables.

01:43:16

They are now properties.

01:43:18

Self is referring to the Q widget.

01:43:22

Remember that originally, I had said, main window equals Q widget.

01:43:29

I'm inheriting Q widget.

01:43:31

So, instead of saying main window, it's kind of like saying self.

01:43:35

My self is a Q widget.

01:43:38

I am a Q widget.

01:43:40

So, I can say self dot set window title instead.

01:43:46

All righty, all the widgets we originally made.

01:43:49

I'm just going to come down here, and let's turn those into properties.

01:43:54

So, self, self, and self.

01:44:01

Looking good.

01:44:03

All righty.

01:44:04

Let's continue down.

01:44:05

You can see that I'm given an error here in my method.

01:44:09

This has become a method.

01:44:11

It's now a function in a class.

01:44:13

Everywhere it says text box.

01:44:15

I don't have text box anymore.

01:44:17

That has become a property, correct?

01:44:21

So, let's just add our keyword, self.

01:44:26

Just like so, and then pass in self as a parameter.

01:44:30

Looking great.

01:44:32

Miss one, self.

01:44:34

Going down this, where we create our buttons, that should be done at the start.

01:44:39

That's done through the initialization process.

01:44:43

So, I can refactor that by putting that just directly inside our constructor in it.

01:44:49

There we go, looking good.

01:44:52

I'm going to give it self here, so self button click.

01:44:56

My grid has become a property, self grid, and our button list is now self buttons.

01:45:02

Already going down, our design, once again, when the app fires up,

01:45:08

in order to start the app, everything should be done at the beginning.

01:45:13

So, all of our design now that we're working with classes, I can remove this.

01:45:18

And I can put this inside in it once again.

01:45:22

I'm going to drop down here, and let's just drop it right there.

01:45:26

All of these, we can tab over.

01:45:29

Remember that anywhere we have main window, we don't have that.

01:45:33

It's now self.

01:45:36

All of these guys have become properties going away from the variable form.

01:45:42

So, let's add self.

01:45:44

Looking great.

01:45:46

All right, so our class has been restructured and refactor.

01:45:51

Let me clean that up.

01:45:53

So, now in it, initialize start.

01:45:57

When the app starts, everything is done.

01:46:00

All the design is done.

01:46:02

All right, because that should be happening.

01:46:04

We then have our method now button click.

01:46:07

That's only triggered when we click the buttons.

01:46:10

And the reason that I can put my design before now is because

01:46:15

this is a class.

01:46:17

The word self unlocks everything in our class that we can use anywhere we want.

01:46:23

We can go to our bottom.

01:46:25

Now, for this to work, if we ran it, well, let's run it.

01:46:29

And let's watch what happens.

01:46:31

It'll make for a better explanation.

01:46:34

I got this massive window blank screen.

01:46:36

That doesn't look right.

01:46:38

Okay, let's close out.

01:46:40

What we need is we can use the Python condition.

01:46:44

That we like to say.

01:46:46

So, if the name, if you're running the main file,

01:46:50

is what this translates to.

01:46:53

If that's the case, then I want my app to run or execute.

01:46:58

I want to create an object.

01:47:00

I want to show that object.

01:47:03

Now, I am using QWage.

01:47:05

Remember, we don't need QWage anymore.

01:47:08

Because we gave this as the super class to our calculator app.

01:47:14

So, this really should be CalCap.

01:47:17

Main window is fine.

01:47:19

I can use that outside here.

01:47:21

Running our app.

01:47:22

It's now brought back to life.

01:47:24

78 minus 35 equals.

01:47:27

There we are.

01:47:28

A refactored form of that app through classes.

01:47:32

Heading over to our last video now.

01:47:34

If you're up for the additional bonus challenge,

01:47:36

we will be learning a new class that I gave you the hint

01:47:40

of using QFont as well as the method of set style sheet

01:47:44

to design your app a little bit more.

01:47:47

I'll see you guys in the next video.

01:48:06

Alright, let's add some design fonts in color to our application.

01:48:20

In order to change the font of our Qline edit and other tools,

01:48:24

let's import QFont.

01:48:26

So I can say from Pi QT5,

01:48:29

this is from the QTGUI module.

01:48:33

I can import QFont.

01:48:37

And QFont, I want to use that to set the font of the text box.

01:48:43

So I can use the method set font.

01:48:46

And inside here, you can see it actually says QFont.

01:48:50

So let's say let's put our QFont class in there

01:48:54

as the argument to our method set font.

01:48:57

And I can actually put the type of font I want.

01:49:00

So let's say a Helvetica as my font.

01:49:05

And then I'm going to style it as let's say a size of 32.

01:49:09

Alright, so that's step one.

01:49:12

We've styled that.

01:49:14

Let's go down a little bit and style the buttons.

01:49:17

So here, we create a button here.

01:49:21

We create a button event.

01:49:23

Before we add it to our layout, let's style it.

01:49:27

So let's use the method set style sheet.

01:49:31

So this is going to allow us to essentially use like CSS in Pi QT,

01:49:38

which is quite cool.

01:49:40

And wherever you are in your programming journey,

01:49:42

you have probably come across CSS in HTML before.

01:49:46

If not, this will be a great time to just briefly read through

01:49:50

some of the CSS guidelines.

01:49:52

So within this method set style sheet,

01:49:56

I'm going to specify a few things.

01:49:58

And I'm going to specify all this as a string.

01:50:00

This is going to be just like normal CSS.

01:50:03

So within any CSS file,

01:50:06

we would typically put the name of the element that we want to affect.

01:50:10

So I want to affect a Q push button.

01:50:12

That would be followed by a set of brackets or curly braces.

01:50:17

The first thing that I want to affect is I'm going to say font.

01:50:20

And I want to give it a font.

01:50:22

And I'm going to say this font is going to have

01:50:24

be 25 pixels or a font size of 25.

01:50:28

And let's be creative here.

01:50:30

Let's say comic sands as our font style.

01:50:35

And then I would like to give a padding as well

01:50:38

of let's say 10 pixels to each button.

01:50:41

So I can specify that like that.

01:50:43

Great.

01:50:44

So each button is going to have this styling to it.

01:50:47

All right.

01:50:48

We haven't added the color.

01:50:49

We've given it a font size, a font family, as well as padding.

01:50:54

Going down to each button now.

01:50:56

Let's take our master layout and let's set our margins.

01:51:01

So this is going to be a small amount of spacing

01:51:04

in between all of our buttons.

01:51:06

And let's say I want there to be 25.

01:51:09

The right left top and bottom.

01:51:12

That's the margins that I'm giving each button.

01:51:15

And I can justify it just like that.

01:51:19

Finally to end things off.

01:51:21

Let's go down to our bottom right here.

01:51:24

I create my main window object.

01:51:27

Before I show my main window,

01:51:31

let's set some styling to this.

01:51:34

Now the question becomes, what do we want to style?

01:51:37

I want to style my entire app.

01:51:40

And our entire main window is our queue widget.

01:51:44

So I can set that like so.

01:51:46

In here, let's just say background color.

01:51:51

And let's give it a background color.

01:51:53

So let's say like, oh, I don't know these.

01:51:57

Let's say one, two, three.

01:51:59

Interesting color.

01:52:00

It's like going to be a really darkish black blue.

01:52:02

Let's try it.

01:52:03

Let's run our code.

01:52:05

Okay.

01:52:06

So unknown background color.

01:52:08

And that's because I spelled background wrong.

01:52:10

You can see the comic sands taking place.

01:52:12

That's really cool.

01:52:13

Let's go down.

01:52:15

Background.

01:52:17

And I also noticed one more thing that we didn't put in.

01:52:20

Oh, okay.

01:52:21

So far too dark.

01:52:23

Right.

01:52:24

I'm not a fan of that.

01:52:26

I'm going to change a few details.

01:52:28

Let's give it like a lighter color.

01:52:30

And I actually have a color right here.

01:52:32

And also, my delete button in my clear button.

01:52:37

They did not have any styling to them.

01:52:41

I'm going to go up.

01:52:42

So I actually create them right here.

01:52:45

I have my self-doctor property in my self-doctor delete.

01:52:48

And both of these are going to be our buttons.

01:52:52

For each button, let's say self-doctor.

01:52:56

Let's say set style sheet.

01:52:58

I'm going to actually take this because I want the same properties as my other styling.

01:53:06

Great.

01:53:07

We can copy this.

01:53:08

And for our last one, let's just set our delete button.

01:53:15

Running our application.

01:53:17

There we are.

01:53:18

It looks amazing.

01:53:19

It looks much better than the last product we had.

01:53:21

Congratulations.

01:53:22

That is the completed calculator application for our course.

01:53:27

Going into the next project.

01:53:28

Let's take what we've built here and build on top of that.

01:53:32

And create an app that's going to add even more functionality that we can use in real world situations.

01:53:39

I will see you guys in the next lesson for our second project.

01:53:43

Welcome to our next project.

01:54:11

In this project, you're going to learn how to combine multiple modules to build an interactive photo editing app in Python with PiQT and the Pill module.

01:54:24

Let's dive in and let's take a look at what this app is going to look like and what it's going to be able to do.

01:54:32

Here's the final product of what we want to get our app to look like.

01:54:36

What can this app do?

01:54:38

Well, we can select an image from a folder from the desktop.

01:54:44

We can apply filters to the image before we edit it.

01:54:50

We can edit all of our photos using the tools that we implement.

01:54:55

And finally, we want to be able to save the photo we edit to our desktop.

01:55:03

Pretty cool.

01:55:04

Now looking at the app, what widgets do you see in this app?

01:55:09

What widgets do you think we're going to import from PiQT to build our design?

01:55:15

Here we go.

01:55:16

How many of these were you able to get right?

01:55:19

Hopefully, all of them.

01:55:21

If you happen to miss any, it would most likely be the Q combo box and the Q list widget.

01:55:30

As we haven't used these widgets yet.

01:55:33

Our Q list widget allows us to have a list of things within our app.

01:55:38

And then the Q combo box is essentially a drop down box.

01:55:43

And the box drops down and it allows you to select an item from that box.

01:55:49

All the other ones you're familiar with.

01:55:52

And you may be thinking, Josh, this is a picture.

01:55:55

Why did you say Q label?

01:55:57

Well, we're going to look at that closely.

01:56:00

But in the initial design of the app, it's easiest if we just set this area to something that's not the picture yet.

01:56:10

So I'm going to say Q label.

01:56:12

In the future, we are going to change the value of this Q label to become a picture.

01:56:21

The final point we need to think about now.

01:56:24

How would you like to design this app?

01:56:28

What's going through your head right now?

01:56:31

Well, so far, you've learned three layouts.

01:56:34

We have our QV box, which is for vertical or columns.

01:56:39

We have our QH box horizontal row.

01:56:43

And then from the last project, you were actually introduced to Q grid layout.

01:56:49

What do you see? How would you design our app?

01:56:53

How I've put it together is I have a master row.

01:56:58

This master row, everything will be added to.

01:57:02

But instead of adding it individually, we can create one, two columns.

01:57:09

We can add the items we need to these columns, then we can append it or add it to our row.

01:57:19

Pretty cool.

01:57:21

Now, before we get into this new module, pill, which is going to help us edit photos with Python,

01:57:28

and before we implement any functionality to our app,

01:57:32

we need to focus on the design of our app.

01:57:36

So far, we have created two projects.

01:57:39

You were introduced to PIQT with our warmup random keyword app.

01:57:45

In the last project, you created your own interactive calculator.

01:57:50

I want you to use the two projects and everything you've learned in these last two

01:57:56

to create our initial design for our app here.

01:57:59

Let me go back. Here is a refresh of what you need to add.

01:58:03

Let's head over to the next video.

01:58:05

But before you do, I want you to at least spend the next 20 minutes.

01:58:10

And I want you to try to design what you see here in VS Code.

01:58:15

I'll see you guys in the next video.

01:58:20

Here we are in VS Code.

01:58:32

In this lesson, we are going to set up our initial project for our app.

01:58:47

Let's jump in and let's set up our initial design.

01:58:56

Starting things off, what do we need to import here?

01:59:00

Well, let's start with our design.

01:59:03

From PIQT5, what widgets do we want to import?

01:59:08

Well, our two most important, we have our Q application.

01:59:12

Let's say Q widget.

01:59:16

What else do we need for this app?

01:59:18

Well, based off what we discussed in our lesson, we'll need a Q label.

01:59:22

We will put in some Q push buttons.

01:59:25

We have a Q list widget.

01:59:29

This will allow us to add the items we select to a list.

01:59:34

We have something called a Q combo box.

01:59:39

Let's start to think about our design.

01:59:42

For the design, we know we're going to have some rows.

01:59:45

And we're going to have some columns.

01:59:48

Great.

01:59:49

I think that's a good starting point for our widgets.

01:59:52

For our alignment tools, who remembers the module for alignment.

01:59:57

We can say QT core.

02:00:00

Specifically, I would like QT.

02:00:03

And we can start with that for our setup.

02:00:07

Great.

02:00:09

I'm going to begin by creating the two objects that we need to start things off here.

02:00:15

So app and let's say main window.

02:00:20

That's our Q widget.

02:00:23

Great.

02:00:24

I would like to set my app title, so set window title.

02:00:29

And let's call this a photo QT.

02:00:32

My version of Photoshop.

02:00:35

Let's set our initial size.

02:00:38

And I can say 907.

02:00:41

Great.

02:00:43

I'm going to jump down and let's get our template shown.

02:00:48

So main window.

02:00:49

Show.

02:00:50

App.execute.

02:00:53

I'm going to give it a quick run to make sure everything checks out before we jump into our design.

02:01:00

There we go.

02:01:01

Great.

02:01:02

Working.

02:01:03

This is the size of our app.

02:01:05

And my template is all ready to go.

02:01:07

We are ready for the next part of our code burger.

02:01:11

Speaking of the code burger, let's label a few things out to prepare us.

02:01:16

All right.

02:01:17

Now that I have things labeled, I'm going to jump here and I'm going to create all the widgets

02:01:21

we want to see in the app.

02:01:23

Now this can be in any order you want as long as we have them all.

02:01:26

So based on the app we're trying to create, I'm going to work left to right.

02:01:31

At the top we have, let's keep it with good name.

02:01:35

So I have a button for my folder.

02:01:38

And this will allow me to click and access my desktop.

02:01:43

So that button will say folder.

02:01:46

Under that, we have our, let's call it our file list.

02:01:50

And this is our queue list widget that's going to contain all the files within the folder that we select.

02:01:59

We are going to have all of our editing buttons.

02:02:02

So now comes the question of what editing tools would you like to add in your project?

02:02:09

You can read some of the documentation and be creative to what you would like to add.

02:02:14

I have selected the following.

02:02:16

So I'm going to create a rotate left button, a rotate right button.

02:02:22

Let's have a mirror.

02:02:24

Let's have a sharpness.

02:02:28

Let's say gray is easier than black and white.

02:02:32

We have a saturation.

02:02:35

And we have a contrast.

02:02:38

I could say blur as well.

02:02:40

That gives our tools more ability.

02:02:43

For each of these, they're each going to be a queue push button.

02:02:47

And each of those will have a string.

02:02:49

So let's just go down and let's add those.

02:02:52

For hate, we have our objects ready to go.

02:02:55

What would you like your buttons to say?

02:02:57

So let's initially say left.

02:03:00

Right.

02:03:01

We can keep all these variable names that we initially use.

02:03:06

We can just keep those.

02:03:08

That brings us to our next widget that we need to add.

02:03:11

I need a drop down box essentially.

02:03:14

So I'm going to call this, let's say drop down box.

02:03:17

And in order to get this into PiQT when you're working with this widget,

02:03:22

this is our combo box.

02:03:25

So let's call this filter box.

02:03:29

And I can say Q combo box.

02:03:31

Now, we need to add the items.

02:03:34

What do you want to see in the drop down box?

02:03:38

Ideally, I want to see all of these in the box.

02:03:42

To do that, we can take our newly created object,

02:03:46

filter box.

02:03:47

And let's use the method add item.

02:03:50

I want to add a single item to my drop down box.

02:03:55

The first one will be my original.

02:03:58

So I need that because when I apply a filter,

02:04:02

I would like to have the ability to revert or go back to my original photo.

02:04:09

So let's say original.

02:04:12

I am just going to go down through each button I created.

02:04:16

And I'm going to add that in here as well.

02:04:20

I now have my combo box with each of my buttons added in there,

02:04:24

which we will use to apply a filter with later.

02:04:27

Very good.

02:04:28

My final item is I want to create an object for my picture.

02:04:34

And this is the actual area in the app that our picture is going to appear.

02:04:40

But initially, we don't have a photo.

02:04:43

So I just want to create an object that I can set as the initial

02:04:48

placement in my app.

02:04:50

Later, changing to insert a photo.

02:04:54

Initially, let's just say Q label.

02:04:57

And the label is going to say image will appear here.

02:05:03

We can just put that text like so.

02:05:06

Awesome.

02:05:07

All of our objects have been created, which leads us down to our app design.

02:05:13

The master layout for my app.

02:05:16

So I'm going to create a master layout.

02:05:18

And I want it to be a row.

02:05:20

So I will set it as a Q H box layout.

02:05:23

Within my master layout, I know that I'm going to have two columns.

02:05:27

So I can create column one and column two.

02:05:31

Let's begin with our first column.

02:05:34

What do we want to see in this column starting at the top?

02:05:38

I want to see the folder button.

02:05:40

And let me show you guys our app.

02:05:43

So this is what we're aiming for in our design.

02:05:46

I want to see this button up top above my Q list widget, my dropdown box,

02:05:52

then all my buttons.

02:05:54

Let's add those two our column one.

02:05:58

The first thing we want is the button for folder.

02:06:04

Next up we would like our file list.

02:06:08

This is the Q list widget.

02:06:12

I would like to see our filter box.

02:06:17

And directly under that, I'm just going to go through.

02:06:20

And I'm going to add each button that we've created up here to our screen.

02:06:26

All of our buttons are here in their added.

02:06:29

So column one is completed.

02:06:31

And column one contains most of our objects.

02:06:35

The only thing that we want to see in column two is currently,

02:06:40

it's just going to be our Q label or the picture box.

02:06:44

Because I want to give my picture as much space as we can.

02:06:48

So we have more editing space.

02:06:51

column one in column two is completed.

02:06:54

What is the next step of our code burger?

02:06:57

Well, let's take our master layout, which is a row.

02:07:00

And we can use add layout to add column one as well as column two

02:07:06

to our master row or the master layout.

02:07:11

The final piece of the puzzle, let's take our main window

02:07:15

and let's set the final layout to become our master layout.

02:07:20

Let's give our app a run.

02:07:23

Here's the app when it's loaded.

02:07:25

Now, it looks a bit strange and that's because this left column

02:07:30

is actually taking up the most room.

02:07:32

That only leaves a little bit for our image.

02:07:35

When in reality, we want to flip this.

02:07:38

We want to have this the opposite way.

02:07:40

I want the first column to take up the least amount of room possible

02:07:45

and give our image the most space we can.

02:07:49

Let's close our app.

02:07:51

I'm going to kill my terminal in here.

02:07:54

I'm going to justify how wide do I want column one to be out of 100%.

02:08:00

Let's say column one is going to be 20% of the entire screen.

02:08:05

This argument is called stretch.

02:08:08

It allows us to justify how much of the screen we want that column to stretch

02:08:13

when we run our app again.

02:08:15

We now have it exactly how we want it to.

02:08:18

All of our buttons are on the left, our editing tools.

02:08:21

And our drop down box has the options that we've added to it.

02:08:25

When we click one, we will have this apply a special filter

02:08:29

to our image to see if we like it before we go and we click the black and white button.

02:08:35

Great.

02:08:36

Our design is done and we're ready to add the functionality to our app.

02:08:40

I'll see you guys in our next lesson where we are going to discuss just how to do so.

02:08:46

Now that we have our app all set up and ready to go,

02:09:14

it's now time to introduce to you this new module that we are going to be working with.

02:09:19

This new module is called the pill module or more specifically the python image library.

02:09:28

Now before we implement any of this code within our project,

02:09:34

I want to take some time to just play with the pill library in its own file.

02:09:40

We can break that down, understand that, then we can take what we learn and use that within our app.

02:09:48

Let's take a look at how this new module is broken down.

02:09:52

The python image library allows us to work with real photos and python.

02:09:57

So imagine the photos you take on your phone or your camera.

02:10:01

We can take those photos and we can edit them in python.

02:10:06

And if you broke this down, this is like a really basic version of Photoshop.

02:10:12

But the more we build on the more advanced we can make our apps.

02:10:18

And if you notice here, I've actually put this how I structured the breakdown of the python framework.

02:10:26

And the pill library is actually quite similar.

02:10:30

Pill is like a massive library or module.

02:10:34

And within pill, we have other modules that we can import individually to achieve a certain task.

02:10:44

Each of these modules contain functions and properties of their own.

02:10:51

This is very similar to how PyQT is working.

02:10:56

We will be using three modules from the pill library.

02:11:00

The first one is called Image.

02:11:03

And this is a class that holds properties and methods specifically for working with pictures as files.

02:11:12

So you should start to think now.

02:11:16

How do we work with files in Python?

02:11:20

How do I load a text file or a JSON file in Python?

02:11:26

Think about that and get ahead start.

02:11:28

The next class that we can look at is Image Filter.

02:11:32

And this is a group of constant variables that we can use to apply filters or rotate our images.

02:11:42

Apply filters or rotate our images.

02:11:46

Remember that.

02:11:48

And the last one is called Image Enhance.

02:11:50

We can use Image Enhance to enhance our images.

02:11:54

So if you're used to Photoshop or the editing tools on let's say Instagram,

02:12:00

there are tools for saturation, contrast and vibrance.

02:12:05

We can use these with Python and we can get those from the image enhance module.

02:12:11

Now that we understand these three modules that we will use from the pill library,

02:12:17

let's take a look at a few code examples in what they actually do behind the scenes.

02:12:23

Here is some of the code that we're going to be using and it's not in any particular order.

02:12:28

Except the first one and the last one.

02:12:30

Because this is the overall structure we will use in the app going forward.

02:12:36

To kick things off, we can import pill, but remember, pill is massive.

02:12:41

And just like PiQT, we don't want to say import star.

02:12:46

There's too much happening.

02:12:48

So be more specific.

02:12:51

What do you want to import and what will you be using in your app?

02:12:56

I can say from the pillow library,

02:13:00

import the image module, class, image filter and image enhance.

02:13:05

And this is the structure to import the classes we are going to be using in this app.

02:13:11

We have a method called convert, convert takes an argument of an L.

02:13:17

Don't ask me why? That's what it is.

02:13:20

And what convert does is it converts this image pick to a black and white image.

02:13:30

Pretty handy, pretty short, and that can be done very quickly.

02:13:35

Next up, we could increase the sharpness of your picture.

02:13:39

Now, by changing the sharpness, this is actually a filter we are applying to the original photo pick.

02:13:49

What do we want to filter?

02:13:51

Well, I want to apply the sharp and filter that is a part of my image filter module.

02:13:58

And it's stored in a variable called sharp.

02:14:04

All right? Now, we've seen the basic image module.

02:14:10

We've seen the image filter module.

02:14:15

Now, let's look at the image enhance module.

02:14:19

If I want to make my picture more saturated or add color, I can do so.

02:14:26

And how we do this is we create our variable and the value is we take our class image enhance and we apply a subclass color.

02:14:36

What do we want to add color to this pick, this original picture?

02:14:42

And I can enhance that by 1.2.

02:14:46

I say 1.2 because the picture begins at 1.

02:14:52

So I'm increasing it by more or less 20% 1.2.

02:14:58

If you want to mirror an image, you can use your image class and you can use something called flip left right.

02:15:06

And finally to save a picture, you can just use the pill save method.

02:15:12

We can link that to our new picture name, and then our picture is actually saved within our desktop or within the escode.

02:15:19

Now, I asked earlier how do we open text files in Python?

02:15:24

And I wanted to get you to think about that because we can do the same thing with an image in Python.

02:15:32

We can use the Python open function.

02:15:36

Take a look at our code, try and interpret what's happening.

02:15:41

If you need to pause the video, please do.

02:15:45

At the top, we always import everything we are going to be needing in our code.

02:15:51

So because I'm using pill and images, I'm going to import the pill elaborate.

02:15:56

Then we can use the open function just like we do with text files with open.

02:16:04

The only difference we need to do is I need to specify what am I opening.

02:16:11

So with open, I want to open a picture called selfie.jpg.

02:16:18

And this picture I load, I'm going to give it a nickname and reference it as pick.

02:16:28

So now, anywhere I use this variable pick, the value of pick is actually the picture we decide to open.

02:16:40

So I can show my picture.

02:16:44

I can then take my picture and I can enhance it.

02:16:49

I can add saturation to my pick, it's being passed down.

02:16:55

If we want to convert our pick to black and white, the same thing.

02:16:59

I can take my new picture variable because I created that and I can convert that to black and white.

02:17:08

Remember, after we do something, if you want to see it, you need to show the new picture.

02:17:17

If you want to save it, you need to save the new picture.

02:17:21

But in this code, did we save the pictures?

02:17:25

No, we didn't.

02:17:26

Do you remember how we save a picture?

02:17:31

We need to use the save method.

02:17:35

I am saving this new picture black and white.

02:17:40

And I'm giving this new picture the name, grey pick, jpg.

02:17:46

Let's head over to VS Code in a new file outside of our PIQT app.

02:17:52

And let's spend the next 10 minutes and let's experiment with how this new library works and how we can use it to edit photos.

02:18:02

You are going to need a few photos.

02:18:05

You can use your own or you can head on to Google and find a few stock photos that we can use.

02:18:11

I'll see you guys in our next video.

02:18:32

Let's take a step away from PIQT.

02:18:41

You have just been introduced to a new module.

02:18:44

This module is called the Python image library.

02:18:47

We use this to work with images in Python, which allows us to open them and edit them.

02:18:53

So, in this lesson, we want to practice and introduce the steps we need to take in order to edit an image.

02:19:01

Everything we learned in this lesson, you will be implementing and using within your PIQT image editor app.

02:19:09

Alright, let's jump in and let's import what we need.

02:19:13

So I'm going to say from the pillow library, I want to import image.

02:19:20

We need image to be able to open the image or do the basic edits to the image.

02:19:26

We are also going to be looking at a class called image filter.

02:19:29

This allows us to apply filters to the image, as well as image enhance.

02:19:35

Image enhance allows us to add contrast or saturation to a picture.

02:19:40

Now that we have that, I'm going to come down here, and we want to open a picture.

02:19:46

So here I have the picture I'm trying to open.

02:19:52

I can delete this one.

02:19:54

Alright, this is the figmologa I want to use this and I want to edit this.

02:19:59

In our main file, I can put inside open my picture name.

02:20:04

Whatever picture you want to use, just drag it into VS code.

02:20:09

So I want to open this picture, and I want to give it a nickname and reference it as picture.

02:20:17

So every time I use this variable, I just made picture.

02:20:21

It's referring to the picture we've loaded in here.

02:20:26

But I can't just open an image in Python.

02:20:30

I'm going to get an error. Open is meant for text files and JSON files.

02:20:35

But because we're working with the pillow library, I need to say, hey, it's actually image that I want to open.

02:20:43

And this image that I open, I'm going to call it picture.

02:20:49

Now that we've done that, let's just run a quick test.

02:20:51

I can say picture.show, and there we have it.

02:20:54

So it's loaded up on our screen.

02:20:56

Great.

02:20:57

I'm going to turn off picture showdown.

02:21:00

Let's start with our editing techniques.

02:21:03

So a nice one to be introduced with is black and white.

02:21:07

Let's say that we want to convert our picture to black and white.

02:21:12

So I make a variable and the value of this variable is our original picture.

02:21:19

And I'm going to take that and I want to convert the original picture to black and white.

02:21:26

Now that I've done that, I can take this new image and I can save this image.

02:21:32

What name do I want to give this?

02:21:34

Well, I could just say gray.png.

02:21:38

When I run this, I'm not showing the picture anymore.

02:21:42

I'm just saving the picture.

02:21:44

So it's going to edit the photo and it should appear here.

02:21:48

Great.

02:21:49

Our code's ran and it has appeared here.

02:21:51

I click that.

02:21:52

There we go.

02:21:53

Our picture has been edited.

02:21:55

We've converted it to black and white.

02:21:57

It looks great.

02:21:58

Let's play with a few more.

02:22:00

Going down.

02:22:01

What is another one we could look at?

02:22:03

Well, let's say we want to rotate.

02:22:06

Or mirror our image.

02:22:10

We looked at these during the lesson.

02:22:12

I won't be doing all of them in this video.

02:22:14

So I encourage you to use what we just learned from the lesson and try the ones that I don't talk about here in our video.

02:22:22

Let's make one from mirror.

02:22:24

I'm going to say, all right.

02:22:26

What do I want to mirror?

02:22:27

Well, I want to mirror my picture.

02:22:29

All right.

02:22:30

What do I want to do with this picture?

02:22:32

I want to transform it or transpose the picture.

02:22:36

Great.

02:22:37

What do I want to do to it now that I can transpose it?

02:22:40

Well, I can take my image.

02:22:42

And I can say, I want to do flip left right.

02:22:46

That's going to mirror our image.

02:22:48

I can take this newly created image.

02:22:51

And I can save this image.

02:22:53

Let's just call it mirror.png.

02:22:59

Running our code.

02:23:01

There we are with mirror.

02:23:03

And you can see the Figma logo is actually flipped.

02:23:06

All right.

02:23:07

If I go to the original, it looks like an F for Figma.

02:23:10

I go to mirror.

02:23:11

It's a backwards F.

02:23:13

That's awesome.

02:23:14

We just transposed and flipped our image with mirror.

02:23:17

We're going to take a look at two more.

02:23:19

I want to use one from each of the classes we've imported.

02:23:24

So I've used image.

02:23:26

And you can see how we used that with our open function.

02:23:29

As well as any type of rotation.

02:23:32

So if you want to mirror or you want to flip the image left,

02:23:36

flip right upside down, we use the image class.

02:23:40

Let's say we want to apply a filter.

02:23:44

So a filter could be like blur or sharpen.

02:23:50

Things like that.

02:23:51

Let's say we want to make the image blurry.

02:23:54

So I'm going to create a new variable called blur.

02:23:57

I'm going to take my picture and I'm going to apply a filter to that picture.

02:24:04

What filter do I want?

02:24:06

Well, I want blur.

02:24:08

And that it comes from the image filter class.

02:24:11

So I can say blur just like that.

02:24:13

We then take it.

02:24:15

We can save it.

02:24:16

Give it a name of blur.

02:24:18

And we can run it.

02:24:20

Now it's quite tough.

02:24:21

It is blurred.

02:24:22

It's just quite tough to see because this is an SVG image.

02:24:26

There we go.

02:24:27

That's blurry.

02:24:28

All right.

02:24:29

Looks great.

02:24:30

I'm going to do two more now.

02:24:33

And both of the next ones are actually going to be from the image enhanced class.

02:24:38

We're going to talk about two ways we can do this.

02:24:41

I would like to begin with the contrast.

02:24:44

So I would like to add contrast to my image.

02:24:48

This is equal to our image enhanced contrast.

02:24:52

What do you want to add contrast to?

02:24:55

My picture.

02:24:57

Okay.

02:24:58

So I am telling Python that I have a picture called picture.

02:25:03

And this is what I'm going to add contrast to.

02:25:07

It's now called contrast.

02:25:10

I'm going to take that variable contrast.

02:25:13

And I'm going to say it's now equal to the original contrast.

02:25:17

But I want to enhance it.

02:25:20

Your photos start on one.

02:25:22

Every photo is one.

02:25:24

A good starting point once we get into coding our app will be like 20%.

02:25:28

So 1.2 would be 20% contrast.

02:25:33

For this, I'm going to go all out.

02:25:34

I'm going to say 2.5.

02:25:35

That's a lot.

02:25:36

So I'm adding a lot of contrast.

02:25:39

I can then take this new image.

02:25:41

Let's save this new image.

02:25:45

Let's run our code.

02:25:48

Look at that.

02:25:49

That is a lot of contrast added to our image.

02:25:51

And it actually looks pretty cool.

02:25:53

We've turned all of our colors if I go to our original.

02:25:57

We came from that.

02:25:58

We went to that.

02:26:00

So you can see the power of this in the power of editing these photos.

02:26:05

I'm going to do one final one now.

02:26:08

What you see here is you see a lot of repeating actually.

02:26:13

There's nothing wrong with this.

02:26:15

This is easier to understand,

02:26:17

especially when you're first introduced to this module.

02:26:20

But we could do this a faster way as well.

02:26:23

Now I'm going to create one for color.

02:26:26

I can say the value of this is image enhance this time color.

02:26:31

What do we want to add color to my picture?

02:26:34

Instead of going to our next line,

02:26:36

I can just link my enhanced method here.

02:26:39

It's the same exact thing.

02:26:42

Let's say 2.5 again.

02:26:44

That's a lot of color.

02:26:46

In our app, let's just try 1.2,

02:26:49

because we will be able to continuously click the button to add more if we want to.

02:26:55

For here, 2.5,

02:26:57

we can take our color and we can save that new image as color PNG.

02:27:03

You can name your images anything,

02:27:05

but the extension they end with,

02:27:08

make sure it's the same extension as the image you originally loaded.

02:27:13

I'm ending with PNG,

02:27:15

so I'm using PNG when I save the images.

02:27:19

Let's run this for the final time.

02:27:23

You can see how much brighter that got.

02:27:26

We added so much more color in there.

02:27:29

Looks great.

02:27:31

We have just gone through and we've introduced and played a little bit with photos.

02:27:36

Before you head into the next video,

02:27:38

I would like you to go find 3 photos.

02:27:41

These could be photos that you've taken off your phone that you want to try editing,

02:27:45

or photos online.

02:27:47

Spend the next 10 or 20 minutes,

02:27:49

programming out a few more edits.

02:27:52

You can use what we talked about in the previous lesson

02:27:55

or you can Google and do some research and read the pill documentation.

02:28:00

What can you find?

02:28:01

Anything you're able to add,

02:28:03

you'll be able to add in your image editing app.

02:28:06

I'll see you in our next lesson.

02:28:10

Let's get started.

02:28:34

Now that you understand how the pillow pill library works,

02:28:38

it's time to implement this to our photo app.

02:28:43

And in our last project,

02:28:45

the calculator app,

02:28:47

as a bonus part of the creation of that,

02:28:50

we did a refactor challenge

02:28:53

where you refactor the app into a class-based application.

02:28:59

We are going to start from the get-go right now

02:29:03

in creating our image editing app as a class-based application.

02:29:09

Here I have two bullet points,

02:29:11

and each of these are actually two different methods

02:29:15

that we need to create.

02:29:18

And I've worded these out before we look at the code

02:29:22

to get our minds thinking about how this can be done.

02:29:27

And after I go through this,

02:29:30

in a file in VS code,

02:29:32

I want you to just type your ideas out.

02:29:35

Spend five minutes.

02:29:36

What would you do?

02:29:38

What do you think is right to solve the?

02:29:41

We need to create a function.

02:29:44

We want to create a function that's going to filter through two lists.

02:29:50

The first is a list of files.

02:29:54

And this will contain all of our photos.

02:29:57

And the second list is going to be a list of extensions.

02:30:01

So think about that.

02:30:03

What extensions do photos end with?

02:30:06

What we want to do is for every file in our file list.

02:30:11

We want to check to see if the file has one of the correct extensions.

02:30:18

Now, our photo extensions should have either JPEG,

02:30:23

PNG, or SVG as their image.

02:30:29

If they do indeed have one of those extensions,

02:30:33

we want to add them to a new list that we create within this function.

02:30:40

Now, as a hint, I've given you a part of the code,

02:30:43

because this is a new PICUTE method we've never used before.

02:30:48

I can use this with a condition.

02:30:50

And I can say, if the current file name I'm looking for,

02:30:54

ends with the current extension I'm looking for,

02:30:58

we can append it to a new list.

02:31:01

You're going to start to see a lot of new methods, actually.

02:31:05

I will do my best to explain them here in the lessons

02:31:09

as you implement them into your code.

02:31:13

Now that we have this first function done, our filter function,

02:31:17

we want to create a function that gets the current working directory.

02:31:22

Now, if you aren't familiar with the directory,

02:31:26

that's okay. Let's introduce you to that now.

02:31:30

You've probably seen this before in VS code.

02:31:34

When you run your code in your terminal,

02:31:37

it displays something like this.

02:31:40

And this is basically where are you within your computer system?

02:31:47

Users is like the main starting point.

02:31:50

At least I'm on a Mac.

02:31:52

The main start of the directory on a Mac is users.

02:31:56

Then it's the current user.

02:31:59

So what this would say is my path.

02:32:02

I want to Mac in the user Josh on the desktop

02:32:07

in a folder named folder one in a file called main.py.

02:32:15

That gets where I'm at.

02:32:17

And that's called our directory.

02:32:19

In order to get my current working directory with PyQT,

02:32:23

I can make a variable.

02:32:26

And the value is a Q file dialog,

02:32:30

and the method is get existing directory.

02:32:34

Now, Q file dialog.

02:32:37

That's a Q. Do we import that?

02:32:40

What do you need to do for that? Think about that.

02:32:43

This function calls the filter function,

02:32:46

and we add the file names to our Q list

02:32:50

widget on the app screen.

02:32:52

So this new function that you're making

02:32:55

is actually going to call the first function we make.

02:33:00

And it's going to take those file names,

02:33:02

and it's going to add it to our Q list widget.

02:33:05

As a hint, here's the actual code we're going to use.

02:33:09

This is the filter function we just made.

02:33:13

And it's taking the current working directory with our extensions.

02:33:20

This is our class.

02:33:23

In the last slide, we introduced the two functions we need

02:33:27

to create outside of our class,

02:33:29

which we are going to use to give a path

02:33:33

or give a file to our class.

02:33:37

We define four properties from the beginning,

02:33:42

because I know taking a look at some other important methods we need in our class.

02:33:48

We do need to create a method to save our image.

02:33:51

But don't worry, because we can still use the piqt

02:33:55

or the pill save method.

02:33:57

But I want to create a method that is going to allow us to do so.

02:34:01

When we want to save an image, we have to check right here.

02:34:07

I need to check if the path that I'm trying to save my image as already exists.

02:34:16

So, for example, imagine you have a picture on your desktop called background.

02:34:24

Then you try to save another picture as background.

02:34:29

We can't do that.

02:34:30

You can't have a picture that has the same name,

02:34:33

because they need their own unique path.

02:34:36

So first, we want to check right here.

02:34:40

If the path already exists,

02:34:43

or the path is the current working directory.

02:34:49

If not, then let's make a new directory.

02:34:55

That's what that says right there.

02:34:58

We can make a new directory,

02:35:00

and we can join that path with our picture.

02:35:04

Then you can save that new picture.

02:35:09

Awesome. That brings us into actually loading our image.

02:35:14

So in the last slide, we loaded a file.

02:35:18

But now we need to take that file,

02:35:21

and we want it to show as an image.

02:35:24

So how can we do that?

02:35:26

Well, let's create a new method to show this image.

02:35:30

And this method will take one argument,

02:35:33

which is actually going to be a path.

02:35:36

Where is this file we are trying to show located?

02:35:41

Remember, in the original opening of the app,

02:35:45

we said the picture was going to be a queue label.

02:35:49

So, let's hide that queue label.

02:35:54

It's now time to show an image.

02:35:57

We can use the QPICSMAP class

02:36:02

from the QTGUI module.

02:36:06

And we're going to give it the image we want to load,

02:36:09

which is our path.

02:36:11

Once we have this image,

02:36:13

we want to give it a width and height,

02:36:15

which it's just going to take the width

02:36:17

and height of the queue label in our screen.

02:36:21

And then we can set the image and show our image.

02:36:26

Set PICSMAP and QPICSMAP are coming

02:36:31

from the module QTGUI.

02:36:34

You must import QPICSMAP at the top of our code

02:36:39

from this new module.

02:36:43

Now that we pretty much have everything,

02:36:46

our class and the app generally are going to work.

02:36:50

But we cannot edit our photos.

02:36:53

Remember, if we click a button,

02:36:55

we want to have the ability to edit the photo

02:36:59

on the button we click.

02:37:01

We want to take what we learned just in the last lesson

02:37:05

while you were experimenting with the pill library.

02:37:09

And bring that into our new application.

02:37:14

Here is just one example of one of our methods.

02:37:18

So let's say we want to add saturation

02:37:22

or add color to our image.

02:37:25

I create a property called self dot image

02:37:29

because remember, my class has these properties

02:37:34

we made at the beginning inside in it.

02:37:37

And it's going to be given one photo in our class.

02:37:41

This photo, no matter what it's called,

02:37:44

we can call it in reference it as self dot image.

02:37:48

The value of the image for this method

02:37:51

is exactly what we saw before.

02:37:54

Remember, when we were introduced to the pill library

02:37:58

in all the new code, this is the same code.

02:38:03

The only difference is we are changing the name

02:38:06

from pick to self dot image.

02:38:10

All right.

02:38:12

After we edit the photo,

02:38:15

we can then call the save method

02:38:18

that we just made, we want to save our photo.

02:38:21

And then finally, you want to show your new photo.

02:38:26

Because this photo is new,

02:38:28

you need to generate a new image path.

02:38:32

Remember, let me go back actually.

02:38:35

I'm going to go back to the very beginning here.

02:38:38

We created a new folder called save folder.

02:38:43

This is the new path.

02:38:46

We need to use this now while we're loading our new image.

02:38:51

I need to join together my current working directory,

02:38:56

my new save folder and my new save file.

02:39:00

All of these final three lines in every method you make

02:39:05

are going to be the exact same.

02:39:07

You can copy and paste them.

02:39:09

Because every time you edit a photo,

02:39:11

you want to do the same three things.

02:39:14

You want to save the image and you want to show it.

02:39:17

The only difference in the methods you are about to program,

02:39:22

you need to change what you want to do with that photo.

02:39:27

You can remember this and you can go back a few slides

02:39:30

and look at what we did in the last video.

02:39:34

Finally, to tie everything together,

02:39:37

you need to link your buttons or your events.

02:39:41

Do you remember from the first two projects,

02:39:44

how do we connect our events in PiQT?

02:39:48

The object has the value of the class that we just made.

02:39:52

We can take the folder button and we can say,

02:39:56

hey, Python.

02:39:57

When this button is clicked,

02:40:00

I want to connect to the function we first made

02:40:04

that allows us to choose the work directory.

02:40:09

Then, once we load all of the images,

02:40:13

we can take our file list

02:40:16

and I want to access the image that I choose from the file list.

02:40:23

To do that, we can make this new function.

02:40:26

We can check if we select one of the items from the file list.

02:40:33

If we do, we want to call the load image method.

02:40:38

We made inside our class editor.

02:40:43

This final function is responsible for loading the image we click

02:40:48

from the QList widget.

02:40:51

We have done a lot.

02:40:53

Now, before going into VS code,

02:40:57

you should go back through and review a little bit here

02:41:00

and take some screenshots.

02:41:02

Try and put all these pieces together in debug on your own.

02:41:07

I'm about to head over there, and I'll see you guys in the next video

02:41:10

where we're going to add the functionality to our image editing app.

02:41:15

I'll see you guys there.

02:41:37

Now that you've been introduced on how we're going to add functionality to this app,

02:41:47

let's jump right in and let's do so.

02:41:50

To kick things off, let's focus on what we're going to be doing.

02:41:55

We want to be able to click a button and unlock your desktop

02:42:00

or access your operating system.

02:42:03

Through this, you'll be able to select a folder from your desktop

02:42:06

that we can open its contents in display within the app.

02:42:11

To open an unlock our operating system in PICUT or Python in general,

02:42:17

we are going to import the OS module.

02:42:21

OS stands for operating system.

02:42:23

We use this when we work with operating systems.

02:42:27

And finally, in order to get an image into PICUT5,

02:42:33

we are going to import something called QPICSMAP.

02:42:38

QPICSMAP comes from the QTGUI module.

02:42:43

Great. We've imported OS, and we have imported our QPICSMAP.

02:42:49

Looking great.

02:42:50

Where are we going to add the functions and our class within our code?

02:42:55

Well, let's go down to the very bottom.

02:42:57

All the functionality that we want to add will take place before the show

02:43:01

and the execute methods.

02:43:04

So let's jump in right here. What do we want to do?

02:43:07

Well, I know that I want to filter the files and extensions.

02:43:13

We know that we want to choose or get the current work directory.

02:43:22

So where are we within our system?

02:43:25

Those are going to be the first two that's going to help us.

02:43:29

So let's create a variable. Let's say working directory.

02:43:34

I don't know what that's going to be yet, but I'm going to need that variable.

02:43:39

And then making a function for filter.

02:43:42

So filter is going to take a bunch of files and it's going to take a bunch of extensions.

02:43:48

Remember that these extensions are what our photo ends with.

02:43:54

So JPEC, PNG, SVG. Something like that.

02:43:59

I am going to create a list here because I want to go through these files and extensions

02:44:04

and I want to check that if they match.

02:44:07

If my file ends with the correct extension, I can add this to my list.

02:44:14

Let's loop through and let's say for every file in all my files.

02:44:21

I also want to loop through every extension in all my extensions.

02:44:28

If the current file that I'm on ends with the current extension, I'm on.

02:44:37

That's a good thing.

02:44:39

I want to append that file to my new list.

02:44:48

Once my loops are done, we can return my list.

02:44:53

Okay, so let me translate that.

02:44:55

I'm creating a list and I'm giving this function a bunch of files and a bunch of extensions.

02:45:02

I'm going to loop through and I'm going to say for every file in the list of files that was given.

02:45:09

For every extension in all my extensions.

02:45:12

If the current file I'm on ends with one of the extensions, I'm going to add that to this list and then finally return this list.

02:45:24

I want to use this function within another function.

02:45:29

I need to create a function that's going to allow me to access my current working directory.

02:45:35

I'm going to say get work directory.

02:45:41

This is not going to take any arguments.

02:45:44

What I want to do here is I want to access this variable and because it's on the outside and I want to change the value.

02:45:51

Let's make that a global variable.

02:45:55

In order to get my current working directory, we are going to use a class from piqt called q file dialogue.

02:46:06

Let's go up to the top of our code and let's actually import.

02:46:11

It can be anywhere and I'll say q file dialogue, just like so.

02:46:17

I can now use this in the function that we were just making, get work directory.

02:46:22

So to access the current working directory, I can take my q file dialogue and say get existing directory, just like so.

02:46:33

So now the variable working directory is holding my current working directory.

02:46:40

I'm going to create a list here called extensions.

02:46:43

And this is the list of all the possible extensions that my photos can have.

02:46:50

So I'm going to put these here for now and where these are going to go are they are going to be passed up to our filter function.

02:46:59

This is the list we're giving and this is the list that we are going to loop through because these are the accepted extension names.

02:47:10

Every photo, if you take it on your phone or if you take it on a camera, it's most likely going to end with one of these extensions.

02:47:19

Now that I have my current working directory and I have my extensions, I'm going to create something called file names.

02:47:28

This is just a variable, but its value is going to be whatever I return from this function.

02:47:38

So the value of this variable is going to be a list results that we get back.

02:47:46

What arguments do I need to give my function?

02:47:49

Well, we need to give it all of our files and all of our extensions.

02:47:54

Where are we going to get all of our files? Well, it's going to be our current list directory or our current working directory.

02:48:04

So I can access my operating system and let's use the list der method function from the OS module.

02:48:11

And I can just give it my working directory. That's the first argument.

02:48:16

This argument is the same thing as my files.

02:48:21

The second argument, I'm just going to give it my list that I'm just created of extensions.

02:48:29

Alright, this looks good.

02:48:32

Once we've done that, I want to take my list.

02:48:36

Where do we want these files to appear in our app?

02:48:40

Well, the correct answer is the Q list widget.

02:48:43

That Q list widget, we have named file list right here.

02:48:49

I want them to appear here.

02:48:51

So I want to make sure that I have a clean slate or an empty list before I load in these new files.

02:48:59

Going down, let's just say file list clear.

02:49:04

Remember the clear method? We learned this in the last project.

02:49:08

I've cleared my file list and I can now loop through my new list file names.

02:49:14

Remember that this is a list because the value is the list that we return.

02:49:20

So my list is called file names for every file name in my list of file names.

02:49:29

What do I want to do? Well, I want to add every item that I come across to my file.

02:49:37

Just like file list, just like so.

02:49:41

Amazing. Alright, we are so close here.

02:49:45

So we have our three starting functions.

02:49:50

We're close to testing our app, but we're not done just yet.

02:49:54

All we need to do to run a quick test is let's connect the button.

02:49:58

So let's take our folder button and let's run a quick test.

02:50:02

Let's use our collective app.

02:50:04

So when the folder button is clicked, I would like to connect to my get work directory function.

02:50:12

Let's run our app.

02:50:14

I'm going to click the folder button and try to load something from my desktop.

02:50:20

It's working.

02:50:22

So when we click the folder button, we unlock our desktop.

02:50:26

You have the ability to go and select the desktop and choose a folder you want.

02:50:32

You just have to click the folder one time and click the open button.

02:50:38

Now, everything within that folder, I have loaded in my Q list widget.

02:50:44

These are all PNG photos.

02:50:46

You could have JPEG.

02:50:48

You could have anything that we specified right here as an extension.

02:50:53

Awesome. The app is looking great.

02:50:57

I want to have the ability to now click one of these and have it load over here.

02:51:04

How can we do that?

02:51:06

Well, let's carry on and let's solve that.

02:51:08

To do this, we want to create our main class.

02:51:12

Our class that's going to store all the methods we make,

02:51:16

as well as be responsible for programming all of our buttons.

02:51:21

I'm going to close this. I'm going to create a class and I'm going to call this editor.

02:51:26

Editor, we do need to have our constructor.

02:51:31

And we need to ask ourselves, what pieces of information do we want to have inside our constructor?

02:51:38

And not even inside the constructor.

02:51:41

What information do we want to have access to within our class?

02:51:47

Well, I know that I'm going to have an image.

02:51:50

Currently, I don't know what it is, but it will have a value.

02:51:55

I will have one called original.

02:52:01

And original is going to be responsible for holding the original image that we can go back to at any point in time.

02:52:09

I'm going to have a file in.

02:52:12

And lastly, I'm going to have a save folder.

02:52:17

Where do I want these new photos to save?

02:52:20

This will be an extension of your current path.

02:52:25

So let's just call it edits.

02:52:27

Edit is going to be the name of a new folder that we start to save things to.

02:52:32

Let's start with all the important methods.

02:52:34

We need a method to load images to save images and to show images.

02:52:40

Let's start with load an image.

02:52:43

This specifically will not actually load the picture in the app,

02:52:48

but it's going to load the file name that we can take.

02:52:53

And then we can load that file name into our app as an image.

02:52:59

This method load image is going to take self as we need to.

02:53:05

Remember, self is like a key, it unlocks our class.

02:53:09

And it will also take the file name that we want to load in our app.

02:53:14

Let's turn that file name into a property.

02:53:18

So I actually already have my property.

02:53:21

I'm taking that same property,

02:53:24

and I'm changing the value to none to become whatever we give this function.

02:53:30

So my argument becomes the value to my property, self-defiling.

02:53:37

All right, great.

02:53:40

Next, we need to create a name.

02:53:43

So the full name of where we are trying to access.

02:53:48

And I can do this by connecting pieces of our working directory.

02:53:55

To do this, we can access our OS module.

02:53:59

And we can say, I want to join together.

02:54:02

I want to connect two paths or two directories together.

02:54:08

So OS path, join.

02:54:11

I want to join together my working directory of where I'm currently in.

02:54:17

And my file name.

02:54:20

Just like that.

02:54:23

After I have this new path called full name,

02:54:28

we want to open this.

02:54:30

So I'm going to take my property self.image that we've created up here.

02:54:36

Currently its value is none.

02:54:38

Who remembers?

02:54:40

How do we open an image?

02:54:42

I want to use the open function.

02:54:45

But I can't just use open alone.

02:54:48

I need to use the pill Python image library.

02:54:53

So let's go to the top of our code and let's actually import pill.

02:54:59

I'm getting ready to use it.

02:55:01

From pill, I want to import image.

02:55:05

What else will we need for this?

02:55:08

Well, I might as well import my other two classes now as well.

02:55:12

Image filter and image enhance.

02:55:17

Look at this.

02:55:19

We are creating this app.

02:55:21

And we have used three modules.

02:55:24

I've used OS.

02:55:26

I've used piqt and I've used pill.

02:55:29

They're all working together to create a single application.

02:55:34

Pretty cool.

02:55:36

Now that we have image, let's return to our class.

02:55:42

I can say image.open.

02:55:44

There we are.

02:55:45

What do we want to open?

02:55:47

Well, I want to open my full name.

02:55:52

This is that path.

02:55:53

I want to open this image now as a file.

02:55:56

We have our image and before I edit the image or do anything.

02:56:01

I want to make a copy.

02:56:04

So I'm going to take my property original.

02:56:08

Right here.

02:56:09

Currently, it's value is none.

02:56:11

But I'm about to give it the value of my current image that I just loaded.

02:56:17

What do I want to do with this current image?

02:56:20

I want to copy this image.

02:56:24

Now anything I do to the pictures through editing.

02:56:28

I always have a copy of that original image.

02:56:32

Load images done.

02:56:34

What is the next method that we want to do?

02:56:36

Well, let's make one to save our images.

02:56:40

That's what this is going to be responsible for.

02:56:43

Every time I edit an image,

02:56:45

I want to have the ability to save this image.

02:56:48

Within our new save folder.

02:56:53

How can we do this?

02:56:55

Well, let's create a path.

02:56:58

And let's save this path is equal to a join path.

02:57:03

And we can join together our working directory

02:57:07

and at the end of the working directory,

02:57:10

I want to just link on the save folder.

02:57:13

So for example, if my current directory is users slash josh,

02:57:18

slash desktop, now I'm going to link on my new folder edits.

02:57:25

Right here.

02:57:26

That's what we've just connected those two together.

02:57:31

Never path.

02:57:33

I now need to check to make sure that this path does not exist.

02:57:39

So does this path exist?

02:57:42

Or is this the current path?

02:57:47

So OS path is derr, is the current directory.

02:57:56

Okay?

02:57:57

If it's not, I am allowed to make a new directory with that name of my path.

02:58:06

I can create a full name again

02:58:09

and just like before, let's say OS path join.

02:58:13

But now the question becomes what do we want to join together?

02:58:17

Well, I want to connect this new path I just made.

02:58:21

And at the end, I want to connect my file name.

02:58:26

That property.

02:58:28

We can take our image and let's call the save method.

02:58:32

What do we want to save?

02:58:34

I want to save my new path that we just made.

02:58:38

Amazing.

02:58:40

All right.

02:58:41

We have our load image.

02:58:42

We have the save image.

02:58:44

Before we do any type of editing,

02:58:46

we need one last method to get everything working.

02:58:51

This method is going to be responsible for showing our images.

02:58:57

So let's call it show image.

02:59:01

This will actually allow an image to appear within our app screen.

02:59:06

This will take the path of the image that we are trying to load.

02:59:12

The first thing we need to do is the place we want to load the image is actually a queue label.

02:59:20

We don't want to see that queue label anymore.

02:59:23

So our queue label is called picture box.

02:59:26

Let's hide the picture box.

02:59:29

Taking that away from our screen.

02:59:32

Next up, let's create an image.

02:59:35

And this is going to be an object of our queue-pix-map class that we just imported.

02:59:42

queue-pix-map allows us to load images into pi-cuti.

02:59:48

It takes an argument.

02:59:51

What do we want to load?

02:59:52

Well, this path.

02:59:54

So I'm giving a path to this class, queue-pix-map.

03:00:00

And queue-pix-map is converting this path to a real image that we can show.

03:00:06

The next question becomes how big do we want this image?

03:00:10

Well, let's actually load our app again.

03:00:13

I want the image to take up all of this space.

03:00:17

This space, remember, is 80% of the screen.

03:00:21

And we said that because when we created our layouts up here,

03:00:27

I justified it as 80% of the screen.

03:00:31

So column 2 is 80% and column 2, it only holds our picture box.

03:00:39

In our show image, let's create two variables with the height.

03:00:43

Let's say the width is going to be the picture box width.

03:00:48

That's literally the width of the whole column 2.

03:00:53

And the height can be the picture box height.

03:00:57

And that's going to take that.

03:00:59

What can we do with this now?

03:01:01

Well, I can take the image that I have created right here in line 119.

03:01:06

In this image, I want to scale it.

03:01:09

So I'm going to take the image and I'm going to scale it.

03:01:12

How big do I want to scale it?

03:01:14

Well, I now have a width and height that I can scale it too.

03:01:19

An image that we load could become distorted.

03:01:23

And I don't want to prevent it from being distorted or weirdly

03:01:27

Deformed in any way.

03:01:29

To do this, I can actually use the QT module.

03:01:33

And remember, in the past, we have used QT for our alignment.

03:01:38

Well, here, I can use QT to keep my aspect ratios of the picture.

03:01:46

This will prevent the picture from being deformed in any way.

03:01:51

We now have an image that we are ready to load.

03:01:55

I'm going to take my picture box and I'm going to set PixMap.

03:02:01

What picture do I want to set to the picture box?

03:02:05

Well, my image.

03:02:07

My image is now set to the picture box.

03:02:10

But remember, originally we hid the picture box.

03:02:15

Let's say picture box I now want to show you again.

03:02:19

Everything is done.

03:02:21

Before you run the app, this is all within a class.

03:02:25

So this isn't going to work just yet.

03:02:28

We need to do a few more things on the outside.

03:02:32

Let's go on the outside.

03:02:34

And let's create one final function.

03:02:38

This function is going to be responsible to display the image that we click from our file list.

03:02:48

So whatever image we click in this function, we want to check to make sure that our file list actually has items in it.

03:02:59

And so I'm going to say, file list the row has greater than or equal to zero.

03:03:05

There's something in the file list.

03:03:08

If that's the case, I would like to get the value of an item that I click.

03:03:14

Let's create a variable called file name and we can say, okay, the file list dot current item.

03:03:21

This will be the current item that I click on.

03:03:25

I would like to get the text value of that item.

03:03:30

And I want to use my load image method right here because I have a file name.

03:03:38

I just made that.

03:03:40

I'm going to give this file name to my load image method.

03:03:45

How can we do that?

03:03:46

It's a method.

03:03:47

Well, before moving on, I'm going to create an object.

03:03:52

Let's say main, I'll say editor.

03:03:56

All right, I have my object.

03:03:58

I can say main dot load image now.

03:04:03

What do I want to load?

03:04:05

Well, my file name.

03:04:07

Then I would like to show the image that I've loaded.

03:04:12

What do we want to show?

03:04:14

Well, I want to show my OS path.

03:04:17

I need to join together the working directory.

03:04:22

With something else.

03:04:25

With my main file name.

03:04:30

I need to connect those two.

03:04:32

This will allow our image to load.

03:04:34

Great.

03:04:35

The final stage is we have an event for our button.

03:04:39

Well, now we want an event for our file list.

03:04:43

So I'm going to say file list when the current row is changed.

03:04:48

We want to connect with our display image function.

03:04:55

Amazing.

03:04:56

Let's give our app a run.

03:04:58

The app is working.

03:04:59

I'm going to go through and select a folder.

03:05:01

Now that I have the folder selected, I can choose one of these images.

03:05:06

Boom, look at that.

03:05:08

I have loaded an image into my app.

03:05:11

I can select any of these images and they are loaded into our app.

03:05:16

This is great.

03:05:17

Well done.

03:05:18

The functionality is coming together.

03:05:21

What do we have left?

03:05:22

Well, our buttons don't edit these photos.

03:05:26

So let's head over to the next video and let's add the editing power to our app.

03:05:32

I'll see you in our next lesson.

03:05:41

Our app is coming to life in the stage of the creation of our app.

03:06:04

It's now time to add the functionality for the editing.

03:06:08

So when we click our buttons, I want to be able to add more color to a picture or convert a picture to black and white.

03:06:16

Let's program all of our buttons.

03:06:18

Let's scroll down to our class editor.

03:06:21

And in our editor class, we have our load image method.

03:06:26

That's great.

03:06:27

I load an image.

03:06:28

I can save an image.

03:06:29

We have show an image.

03:06:31

I'm going to go down here and I'm going to start to create all the editing tools we have.

03:06:36

So let's just start with our first method and I will call this gray.

03:06:41

Now this method, we are going to program and it's going to be very similar to the lesson we have that introduced you to the pill module.

03:06:51

If you go back, a few lessons to the lesson that we spent time practicing and introducing the Python image library,

03:07:00

we want to use the same idea and the same core concepts in programming our methods.

03:07:05

So I'm going to take my image.

03:07:08

Remember we made a property called self dot image.

03:07:12

This currently holds the value of the image that we loaded into our app.

03:07:18

And I want to change that image.

03:07:21

I want to convert this image.

03:07:23

So I can use the convert method and give it the argument of L.

03:07:29

So I'm changing the image to black and white.

03:07:34

Once I have this new image, let's say self and let's call our save image method.

03:07:41

So I can save this new image into my edits folder that we created.

03:07:49

Next up, I need to create myself a new image path because I want to show this new image.

03:07:56

It has a new path because we generated a black and white image and we saved it into a new folder with a new name.

03:08:08

This new image path.

03:08:10

Well, I want to take my path that I want to join together.

03:08:15

What do we want to join together?

03:08:17

Well, my working directory with my save folder with my file name.

03:08:24

That's a new path.

03:08:26

We can now take our show image method and we can show this new image path.

03:08:34

That's it. That's our gray method.

03:08:37

We edit our photo.

03:08:39

We save the new photo.

03:08:42

We show the new photo.

03:08:45

That is what's happening in this editing function.

03:08:48

Now that we have that, the only thing to do to test if this is working

03:08:52

is we can go down and we need to create all of our events.

03:08:56

The final step is I need to take my black and white button.

03:09:00

When that's clicked, we want to connect to our gray method.

03:09:06

That's inside our class.

03:09:08

We can now give this a quick test before we write any other methods.

03:09:12

I'm going to select a folder.

03:09:14

Now that I've loaded everything in, let's choose one.

03:09:17

I'll choose a colorful one here.

03:09:20

Okay, this is pink.

03:09:21

I'm going to click my black and white button.

03:09:23

Oh, voila.

03:09:24

It is working.

03:09:25

It has been converted to black and white.

03:09:27

That's great.

03:09:28

All right.

03:09:29

Let's work on the other buttons.

03:09:31

I'm going to close my app.

03:09:32

Let's trash the terminal.

03:09:34

Now all of the methods are actually the same thing.

03:09:39

Accept what we are doing to the image.

03:09:44

But the idea of saving the image, creating a new path in showing the image,

03:09:50

that's the same for every button.

03:09:53

For example, if I just take this method and I'm going to paste that here,

03:09:59

let's change this to say left.

03:10:04

Take our image now and let's change what we want to do to it.

03:10:09

So do you remember how do I rotate an image left right?

03:10:14

Well, I can take my image and I want to transpose that image.

03:10:21

As the argument, I'm going to take my class and link the property, rotate 90.

03:10:29

That's it.

03:10:30

We have a new method.

03:10:31

It's the same exact final three lines.

03:10:34

We just need to now connect our left button.

03:10:39

All right.

03:10:40

I want you guys to pause the video here.

03:10:42

And I want you to program the rest of your buttons.

03:10:46

Use the knowledge you gained with the Python image library

03:10:50

and use the knowledge from these first two methods to complete this challenge.

03:10:55

Pause the video now.

03:10:57

I'm going to go through and I'm going to program the rest of these.

03:11:00

I've just finished up programming the remaining methods.

03:11:03

And as you can see here, we have our gray left right.

03:11:06

We have mirror sharpen, blur color contrast.

03:11:11

They're all doing the same thing in the end.

03:11:14

The only difference is what we're doing with that photos specifically.

03:11:19

The final step is each method needs to be connected to its button at the bottom of our code.

03:11:26

Remember, take our button when it's clicked.

03:11:29

We want to connect with one of the methods that we made for that button.

03:11:34

Everything's working.

03:11:36

Let's run our app.

03:11:38

And at this stage, 80% of what we're trying to accomplish is done.

03:11:44

Here's my app.

03:11:45

I'm going to load a new folder.

03:11:47

Now that I've loaded the folder, let's start with Python.

03:11:50

So I can click left.

03:11:52

Ooh, there we go.

03:11:53

Let's click right.

03:11:54

That's working.

03:11:55

Mirror.

03:11:56

It's flipped it.

03:11:58

Our buttons are working.

03:11:59

We're editing real photos with our code.

03:12:02

Let's do color.

03:12:04

If I keep clicking it, you can see that it's getting brighter and more colors being added.

03:12:09

If I click contrast, it's contrasting.

03:12:12

And then finally, blur will be, oh, it blurred well.

03:12:15

I thought that may be tough to see with the Python image.

03:12:18

If I take it, I click blur again.

03:12:20

It's become blurry.

03:12:22

Black and white loses its color.

03:12:24

Our app is coming together.

03:12:26

And this is the most advanced app that you've created yet.

03:12:29

The last thing we need to do is we need to program this filter box to apply a filter.

03:12:36

Remember that we can apply a filter.

03:12:39

It's not going to save that as a new photo.

03:12:42

We can apply a filter and see if we like it before we edit the photo.

03:12:48

In order to do that, we're going to introduce a new and popular Python topic,

03:12:53

which is slightly advanced.

03:12:55

And that's the topic of lambda functions.

03:12:59

I'll see you guys in the next video where I will introduce anonymous functions.

03:13:25

As we approach the end of our project, it leaves us with one final task of adding functionality.

03:13:35

We have not programmed our filters or the filter drop down box.

03:13:41

And that's what we're going to look at here in this lesson.

03:13:44

But to do this, we have so many filters.

03:13:47

I don't want to create a method or a function for each filter because that's repetitive.

03:13:53

And we sort of did that just in our class.

03:13:56

I want to create anonymous functions that I create and I use them right when I create them.

03:14:05

Those are called lambda functions.

03:14:08

This special feature comes with Python and it's for creating anonymous functions,

03:14:13

which are these special functions that don't really have a name.

03:14:17

Most of the time when we create functions, we do define a name.

03:14:22

So we can call on them later.

03:14:25

But with lambda functions, we create it right where we need it and we call upon it immediately to run.

03:14:32

So they don't need a name.

03:14:35

This is called anonymous functions or in our case with Python Lambda.

03:14:40

And this is a slightly more advanced topic that we are getting to explore.

03:14:44

Let's check out two live lambda code examples.

03:14:47

I'm going to explore the first code example up here.

03:14:51

I have a function called cube.

03:14:55

And cube is an anonymous function because yeah, in this case I have given it a name.

03:15:01

But when I call this, it's going to run instantly.

03:15:05

Now I'm saying it's an anonymous lambda function and I'm giving it something here.

03:15:12

This something is used in our expression.

03:15:17

What could these be?

03:15:19

In lambda lambda is taking a single parameter in this example.

03:15:25

I am justifying a single parameter and then that parameter is used in the expression of the function or what we want to do.

03:15:35

So four is really saying four cubed.

03:15:40

Let's add some color coordination.

03:15:42

In the bottom example, I've actually written out a scenario.

03:15:46

So imagine you have your math problem you're trying to solve by multiplying two numbers.

03:15:52

Instead of writing a function for this somewhere in your code, I am writing the function in one line right when I need it.

03:16:02

And that's going to solve this specific problem.

03:16:05

Now because we're multiplying two together, I am giving my anonymous lambda function one two parameters.

03:16:15

If I have my two parameters, we're giving it two arguments when we use it.

03:16:21

These are being used in here.

03:16:23

So if we ran our code, what would be the output of both of these anonymous functions?

03:16:29

Well, the first output would be 64 and our second output would be 15.

03:16:35

So you kind of have a core understanding now of what is lambda, what it accepts and how we create a basic lambda function.

03:16:44

But how can we use this in our project?

03:16:47

Well, let's break that down a bit more.

03:16:50

Our mission with lambda is to create an anonymous function for each filter that we have in our Q combo box.

03:16:59

So I've kind of given you a head start, but how could we do this with a dictionary?

03:17:07

Because it seems very repetitive and I'm going to have a lot of these filter options.

03:17:15

So instead of creating these in seven lines or however many we have, why not store them in a dictionary?

03:17:24

Now remember, a dictionary key value.

03:17:30

And what this would translate to is dictionary key unlocks of value.

03:17:36

So we can use that to structure our dictionary.

03:17:40

Hmm, that's interesting.

03:17:43

What would this look like in our code?

03:17:45

Here I create an instant lambda function.

03:17:48

And when this is used it's going to be executed and ran immediately.

03:17:53

This is a dictionary filter mapping.

03:17:57

And remember, in a dictionary we have a key and every key has a value.

03:18:04

Together, these are called our key value pairs.

03:18:08

So the key is actually the text from our dropdown box.

03:18:15

And the value is this anonymous function that's going to take an image.

03:18:21

The image that it takes, it's going to convert that image to black and white.

03:18:28

That is really interesting.

03:18:31

That makes our code run a lot faster.

03:18:34

And it allows us to create these little functions that we want to call upon throughout our program.

03:18:39

And you can see for every item in the dropdown box I'm making a key value pair,

03:18:46

which represents the dropdown box name and a lambda function.

03:18:52

Here is the overall function.

03:18:54

So let's say we create it and we name our function apply filter.

03:18:58

I'm going to give one parameter of a filter name.

03:19:03

This is the name that we select from the dropdown box.

03:19:09

If I click black and white then black and white is going to be given to this method.

03:19:16

The first thing I want to do is I want to check if I chose original.

03:19:21

Because if I did I want my image to actually be the copy that we first made when we loaded the image.

03:19:30

I want to revert to the original copy.

03:19:34

If we do not choose original it must mean we did something else.

03:19:39

So here is our dictionary of everything else that we have the ability to choose from our dropdown box.

03:19:48

Each of these keys has an anonymous function that will be executed instantly.

03:19:54

And they all take the same parameter image which you can see are being used within the anonymous function.

03:20:03

Now this dictionary nothing is happening.

03:20:06

If we get to else we are going down here and we're checking.

03:20:12

We want to get whatever the filter name was from our dictionary.

03:20:20

Remember that this filter name is actually the parameter that we gave.

03:20:25

We can check to make sure that yes we do indeed have text from our dictionary.

03:20:33

And we can go about our day. We can set our image to whatever image we chose from our dictionary.

03:20:40

We can save that image.

03:20:42

Generate a path and show the image.

03:20:46

Just like how we created our methods in our class.

03:20:50

In certain the dictionary taking the value of the filter function is whatever the lambda function returns.

03:20:58

If lambda returns something we want to show what lambda returned.

03:21:03

Let's check back to our code.

03:21:05

And let's implement this final apply filter function and get you guys writing your first anonymous lambda functions.

03:21:12

I'll see you in the next lesson.

03:21:28

Now that you've been introduced to lambda and anonymous functions.

03:21:43

Let's create a method that's going to store many anonymous functions.

03:21:49

And these functions will be responsible for applying our filter.

03:21:55

Let's scroll down to our class and in our class we can go pretty much towards the end actually.

03:22:00

Let's go all the way down before the final one.

03:22:05

So I can go right in here.

03:22:07

Let's create a method that I can call this apply filter.

03:22:12

Needs our word self.

03:22:14

And then what do we want to give it?

03:22:16

Well, I'm going to give it a name.

03:22:18

More specifically, whichever word that I choose from the dropdown box.

03:22:24

I want to take that text value and I want to use that within this method.

03:22:30

So I'm giving this method a text value from my dropdown box.

03:22:35

Let's just call this filter name.

03:22:39

The first thing I want to do is I want to check if my filter name is equal to original.

03:22:49

Because if it is, I want to revert or change the image back to the initial starting image.

03:22:58

I can do this by saying, okay, cool.

03:23:01

Self.image in that case is equal to self.original.copy.

03:23:10

So our image is equal to the copy that we generated earlier.

03:23:15

Right?

03:23:16

That's why we made the copy to be able to go back to the original copy.

03:23:22

Else.

03:23:24

If it's not original, then okay.

03:23:26

I have selected something that I want to actually apply a filter on.

03:23:32

Now, in our dropdown box, if I were to go check, we have all of these.

03:23:38

So two, four, six, I have eight different options.

03:23:43

And each option is going to be able to do something or have its own function.

03:23:49

So the best way to do this would be to create a dictionary where each of these would be my key in the value is going to be a function.

03:23:58

That's triggered only one time.

03:24:01

That's why we create a lambda or anonymous function.

03:24:05

I'm going to return to our method that we're making.

03:24:08

And let's create a dictionary.

03:24:12

Let's say mapping.

03:24:14

Now, I need a key.

03:24:16

And the first key, let's just start with black and white.

03:24:20

And let me make sure.

03:24:23

These, the text value, needs to match what we're trying to do.

03:24:28

So black and white's good.

03:24:30

Make sure you're spelling is consistent.

03:24:32

Returning black and white.

03:24:36

And the value is now going to be a lambda function.

03:24:39

So to create a lambda function, we're going to use the word lambda.

03:24:43

Then I need to justify any parameters my function will use.

03:24:49

The parameter, well, it needs an image that it's going to edit.

03:24:53

So this function doesn't have a name because it's only being called when I get to hear.

03:25:00

So it's a function, it's anonymous, it has no name.

03:25:05

But this anonymous function, it does have a parameter, which means I'm going to give it an argument.

03:25:13

Next up, in the function, it is going to take what I give it.

03:25:18

And it's going to convert that image to black and white.

03:25:25

That's what it's going to do.

03:25:27

One and done.

03:25:29

All right, so next up, let's try one more together.

03:25:31

Let's say color.

03:25:33

Color is going to be a lambda function.

03:25:36

It takes a parameter of an image.

03:25:40

Let's take what we give it and let's say image and hands dot color.

03:25:45

What do we want to enhance the color of?

03:25:48

Well, the image we give it.

03:25:50

How much do we want to enhance it by?

03:25:53

Let's say 1.2.

03:25:54

Just like when we programmed our method above, right here, same thing.

03:26:01

I have now created two anonymous functions.

03:26:06

I want you to try to program the rest of these lambda functions on your own.

03:26:11

Pause the video here.

03:26:13

I'm going to go through and I'm going to complete the rest of these lambda functions.

03:26:17

What do we want to do to that photo?

03:26:20

The new concept, though, is creating an anonymous function.

03:26:25

Now, remember that this anonymous function is a special Python function.

03:26:29

That doesn't have a name.

03:26:31

And it can perform any task we assign it without meeting a name as well.

03:26:37

So I am giving a parameter of image and we are taking whatever we give it

03:26:43

and we're going to apply and edit to it.

03:26:47

Great.

03:26:48

So I've created this dictionary now and my dictionary is called mapping.

03:26:54

Well, I now want to map over this and I want to get one of these.

03:27:01

I want to get the one that is equal to my filter name.

03:27:08

Let's create a function.

03:27:10

Let's say filter function.

03:27:13

And the value of this is I'm going to take my dictionary and I want to get,

03:27:18

what do I want to get?

03:27:20

Well, I want to get whatever the filter name parameter of this method is.

03:27:26

That's the value of filter function.

03:27:29

I now want to check to make sure that there is a value that we selected.

03:27:35

So to do that, I can just say if filter function.

03:27:40

Right?

03:27:41

That translates to if filter function equals true or if there is something in our filter function.

03:27:49

If there is, what should we do?

03:27:51

Well, let's take our image, right?

03:27:54

Our property, self.image.

03:27:56

And we're going to say, hey, I want to update this.

03:27:59

And I'm going to update this to the value that we gave our filter function, self.image.

03:28:08

I can then save, let's call our save image method.

03:28:13

I can create an image path just like we did in our initial method.

03:28:18

So OS path, join.

03:28:21

We want to join together many things, working directory, our save folder,

03:28:27

and then finally our file name.

03:28:32

What do we want to do last?

03:28:34

Well, then I can show this new image that we have.

03:28:37

Kind of created or at least applied the filter to.

03:28:41

So image path.

03:28:43

Finally, if that fails, let's just say pass.

03:28:46

I want to skip over it.

03:28:47

So our apply filter function, or I should say method is done.

03:28:51

We have a method in this method contains about eight other functions, which is incredible.

03:28:58

Now that most of the supply filter method is done, we're pretty much there.

03:29:04

Outside of my else.

03:29:06

So no matter what, when this condition is done running.

03:29:11

I would like to save the image.

03:29:15

So let's call our method, we made save image.

03:29:18

Let's take our image path and let's show our image.

03:29:22

So I'm going to take those and I'm going to put those just like that right there.

03:29:27

Looking great.

03:29:29

We want to create a function on the outside to handle any of this.

03:29:33

So let's say let's create a function called handle your filter.

03:29:38

And the first thing we need to do is we need to make sure that, indeed, there are items that have been loaded into our Q list widget.

03:29:48

So just like we did in the other one, let's make sure that we have an item.

03:29:53

What do we want to do with that item?

03:29:55

Well, I want to get text.

03:29:58

So bear with me.

03:30:00

Whenever item I click from the drop down box, I want to get that text.

03:30:06

In order to do that with a Q combo box or a Q drop down box, we do not use the text method.

03:30:14

Instead, what we can say is let's take our filter box and let's use the method current text.

03:30:22

Now that we have the current text value, let's call the apply filter method.

03:30:28

Giving it the text that we just created or got.

03:30:34

Our final stage is we need to create our event for our handle filter method.

03:30:41

We can take our filter box and we can say hey, when current text is changed,

03:30:49

we want to connect to this new filter function.

03:30:55

Now the current text is initially original because it's the original photo.

03:31:02

When we change that, all right, now we want to trigger this event.

03:31:08

Amazing.

03:31:09

Let's run our app.

03:31:11

I can now load in a folder and let's go through and choose one of our images.

03:31:16

So let's choose this will be perfect.

03:31:20

In my drop down box, I can now choose.

03:31:23

How would this look as a black and white image?

03:31:26

Oh, that looks pretty good.

03:31:28

Okay, let's go back to the original.

03:31:32

Great.

03:31:33

Now, how would it look if we blurred it?

03:31:37

Well, I can't really tell, right?

03:31:40

So I'm going to go back to the original again.

03:31:43

Everything is working.

03:31:46

This is great.

03:31:48

Well done.

03:31:49

You guys have a completely working image editing app that we've created.

03:31:54

We have access to our desktop using the OS module.

03:31:58

You've used multiple modules from PICUT and we've used a few classes from the pill module as well

03:32:06

to achieve this.

03:32:08

Well done.

03:32:09

I'm so proud of you guys.

03:32:11

If you're interested, head over into the next lesson where I've prepared a special challenge

03:32:16

using Lambda to extend the functionality of our photo QT image editing app.

03:32:23

I'll see you in the next lesson.

03:32:42

Congratulations.

03:32:43

We have a working image editing app fully completed with the editing capabilities that we wanted

03:32:49

as well as Lambda functions.

03:32:51

Now, let's refactor our code.

03:32:54

And I've prepared a challenge for you guys using anonymous functions to make our image app more efficient.

03:33:02

Let's take a look.

03:33:04

Currently, we have a class.

03:33:06

And our class has all of our editing methods in.

03:33:10

Right?

03:33:11

So every button we have, we created a method for.

03:33:14

I want to see if you can take all these editing methods and convert them into this.

03:33:23

Can you replace all the buttons and how can we use Lambda to do so?

03:33:28

I want you to try to create a new method which is going to replace all of these.

03:33:34

You can name this method, transform image, or if you have a better name, use that name.

03:33:39

This method will hold a dictionary just like our previous method.

03:33:44

With all these functions we want to replace, or I should say update.

03:33:50

If you're up for a good challenge, this is better going to improve your understanding of how to use anonymous functions,

03:33:57

as well as using dictionaries.

03:33:59

I'll see you in the video where we've refactor our app and add in this final method.

03:34:09

You must be up for the Lambda challenge if you're here and I'm glad you are.

03:34:25

We're going to refactor this code and make it significantly more efficient and less, all while keeping the same functionality.

03:34:33

Let's take a look right here.

03:34:35

We have all these buttons and we want to create a Lambda function for each button.

03:34:43

This is going to be very similar to how we created them for the filter.

03:34:49

Let's take a look at our class.

03:34:51

We have our editor.

03:34:54

Within here we have init, we need that, we have load image, save image, show image.

03:35:01

We need to keep all those because they each have an instrumental task that is called upon at some point in our program.

03:35:08

But all the other methods, the ones where we create the actual editing techniques,

03:35:15

you can see here that I have 1, 2, 3, 4, 5, 6, 7, 8, you have 8 of those.

03:35:25

What if we could replace all of those with a single function?

03:35:29

Well, that's what I'm going to do.

03:35:31

I'm going to take all the methods that we just programmed and I'm going to delete them from my code.

03:35:37

What you can do before you delete is maybe make a copy to keep this and you're able to see how far you've come.

03:35:45

And we have a starting point, which is this, and now we're progressing into a more advanced concept.

03:35:53

So I'm going to delete those. We have our applied filter method.

03:35:57

Currently now I have, if we go down to all of our events, we have none of these anymore.

03:36:02

Right, main mirror, mirror is not a method, we just deleted that.

03:36:06

Let's go up here, just above our applied filter method.

03:36:09

We are going to make a new method here, and we can call this transform image.

03:36:16

Transform image is going to take something, so transformation.

03:36:21

What do we want to do to the image?

03:36:24

If I click the blur button, blur is my transformation.

03:36:30

It is very similar to how I explain a filter name in the apply filter method.

03:36:38

Inside here, we will make a dictionary.

03:36:41

The dictionary is going to be structured the same way as we did here.

03:36:47

So I can actually take most of these out. Let's just copy those, paste those here.

03:36:54

What do we have? One, two, three, four, five, six, seven, eight. Those are all of our buttons as well.

03:37:00

And just double check that these text, these strings, all match your button names at the top.

03:37:09

And if I do a quick check, they do match.

03:37:13

Going back down to this new transform image function.

03:37:17

We have a dictionary inside that each of these is a key value pair.

03:37:25

The key is what the button says, and the value is an anonymous function.

03:37:31

Our anonymous function will take an image, and it will do something with that image.

03:37:39

We have all of our functions ready to go in our transformation dictionary.

03:37:44

Let's create a transform function.

03:37:48

And let's just say, I'm going to say transformations.

03:37:52

I want to get the transformation I give as the parameter.

03:37:57

This is my dictionary. I want to get something from the dictionary, and I want to get the original parameter.

03:38:05

We passed into our method.

03:38:09

Just like our applied filter method, I'm going to check to make sure this is true.

03:38:13

I indeed have something.

03:38:15

Because if we don't have anything, well, I can't quite do anything with it.

03:38:20

If I do, though, I'm going to take my image, and I want to update my image.

03:38:25

This is now my image.

03:38:29

After we apply our filter to it, we can save this new image.

03:38:34

Finally, we can show this new image.

03:38:39

Just like that.

03:38:41

I have replaced all eight of our original methods with a single transform image method.

03:38:49

All that's left to do is we need to connect our methods to our buttons.

03:38:54

And because we're using Lambda, this is going to be slightly different.

03:38:59

Where do we keep all of our events?

03:39:02

Well, they're at the bottom. Let's head to the bottom.

03:39:05

Starting with our first button, gray.

03:39:08

Now, I'm going to change what we're connecting to.

03:39:12

We are connecting to a method, but that method is a Lambda anonymous method.

03:39:18

Or it's an anonymous function in our method transform image.

03:39:23

Lambda is an anonymous.

03:39:26

I can take my main object, that's my class, remember.

03:39:30

In two, our main class, we can link our method we just made, which is transform image.

03:39:37

I now need to select one of the keys in transform image.

03:39:43

So if I go up here for the gray, the black and white, this is my key.

03:39:49

I'm going to use this in here.

03:39:52

I can just say black and white.

03:39:55

If I go to our next one, I would do the same thing.

03:39:58

I would take Lambda, and I would say our object.

03:40:01

Let's transform our image, and I think we just call that one left.

03:40:06

If I go up and check, yep, right there left.

03:40:09

I'm going to go forward and program the rest of these.

03:40:13

All right, we have all of our new Lambda functions connected.

03:40:17

That means it's time for us to run our app.

03:40:19

All right, and just right here, so I'm trying to show an image.

03:40:22

But if we remember, show image takes a path, which I've left out here.

03:40:28

So let's come out here.

03:40:30

I'm going to do a few things.

03:40:33

Outside, I can do save image again.

03:40:37

Then directly inside, let's create an image path again.

03:40:40

We can say OS, path, I want to join.

03:40:43

What do we want to join?

03:40:45

Well, I want to join my working directory.

03:40:47

I want to join my save folder that we have created.

03:40:52

So save folder, and then finally our file name.

03:40:56

And we can just do a check.

03:40:58

Does this match this?

03:41:01

It does.

03:41:04

Our app is running, selecting a folder.

03:41:07

Going down to our images, left.

03:41:10

Great, it's working, right?

03:41:13

There we go, I can mirror it.

03:41:16

I can add color to it.

03:41:21

There we are.

03:41:23

Contrast.

03:41:24

All of our buttons are working.

03:41:26

They look great.

03:41:27

Amazing.

03:41:28

We just refactor our project to more efficient code.

03:41:31

You have been introduced to so many new concepts in this project.

03:41:35

One, the introduction to a new module, pill, the pillow library, for working with images.

03:41:41

Two, you have now been introduced to anonymous functions and python.

03:41:45

Which I'm sure you've seen before.

03:41:48

These little guys are called lambda functions.

03:41:51

As well as taking your piqt skills to the next terror.

03:41:56

Amazing job.

03:41:57

Congratulations.

03:41:58

I'll see you guys in the next lesson for the start of our next project.

03:42:15

Congratulations as we enter our next project.

03:42:33

You guys have done an incredible job.

03:42:35

You have so far three fully working apps.

03:42:39

With one warmup or introduction app for piqt, you have a fully working calculator application.

03:42:44

And after completing the last project, you now have an image editing app.

03:42:50

As we enter this project, you are about to make an expense tracking app.

03:42:55

But this app is going to do so much more than just track your expenses and use your knowledge of piqt.

03:43:01

Not only are you going to use and build on all of your piqt knowledge.

03:43:06

You are also going to get an introduction to sequel in how we can incorporate

03:43:12

SQL databases into our app to track and maintain live data.

03:43:19

More specifically live data that's changing.

03:43:22

So in the last project, you got an intro to lambda in anonymous functions.

03:43:27

Add that to the CV.

03:43:29

In this project, you're going to get an intro to sequel in what that is and how we can use that with apps.

03:43:36

Let's take a look.

03:43:38

This is our overall app overview.

03:43:40

Our app.

03:43:41

We have the ability to add expenses, delete expenses, and also save data in a database.

03:43:50

And I want you to think, what widgets are you seeing on the screen?

03:43:56

You should know most of these.

03:43:59

Right?

03:44:00

We have been using these in previous projects.

03:44:03

So what widgets do you know?

03:44:05

Well, let's take a look.

03:44:09

All of these widgets we will be using in our app.

03:44:12

And you can see right from the get go, there are two that you may be unfamiliar with as we haven't used them before.

03:44:18

We have our Q date edit in Q table widget.

03:44:23

Now, you can see that the date edit is collecting a date.

03:44:28

We even have a category that's going to allow us to choose what category our expense came from.

03:44:36

We have the ability to enter the amount of the expense, as well as a description of what we spent it on.

03:44:44

We create two buttons.

03:44:46

And at the bottom here, we have our visual database.

03:44:51

So this is the front end of what we see once we add all of our data using sequel to our sequel database.

03:44:59

Have you thought about your design yet?

03:45:01

Because as you're growing more and more of an expert with PiQT,

03:45:05

you should be thinking about your design every step of the way.

03:45:09

How could we design this app?

03:45:11

Well, let's take a look.

03:45:13

I have created one master column, and you can see I'm using QV box layout.

03:45:19

I have three rows at the top with a few objects in each row.

03:45:25

My table does not need a row because it's going to take up my whole screen.

03:45:31

Everything else I want is actually above my table.

03:45:36

While you're designing this app, you know most of the methods in the ways that you will be able to implement your designs.

03:45:43

But QTable widget, this is new.

03:45:47

And you will need to import this along with your other QT widgets.

03:45:51

In order to get your table set up, there is a method that comes with our QTable widget class.

03:45:58

We have set column count.

03:46:01

And this takes an integer as an argument.

03:46:04

And you can see that in this example, we have five columns.

03:46:09

If I put the number five inside here, we will see one, two, three, four, and five.

03:46:18

That allows us to structure our database and get it ready to accept data.

03:46:24

The second method that we are going to use is called set horizontal header labels.

03:46:29

This method takes a list.

03:46:32

More importantly, this list is going to have many elements.

03:46:35

Each element will be a string.

03:46:37

And the string will be the name of your columns.

03:46:42

If you say you have a column count of five, then in your list, you should also have five elements.

03:46:51

Each element is representing the name of your headers, the name of your rows.

03:46:59

Let's head over to VS Code.

03:47:01

And let's try and get our app designed and structured before we dive into SQL.

03:47:06

I'll see you over in the next lesson.

03:47:21

Now that we're here in VS Code, let's get our expense tracker project all set up and designed.

03:47:40

You can see here on the screen, this is what we're aiming for.

03:47:44

And by the end of this video, we will have an initial design, something like this ready to go.

03:47:50

Let's move that away from now.

03:47:52

I have here my codeburger, and what do we need in order to design this app?

03:47:57

Well, a lot of things.

03:47:59

But in this video, we are just going to focus on one module, QT widgets, because we need to design our app first.

03:48:07

And that's what we can start things off with.

03:48:10

In the previous projects, we have created an app.

03:48:15

Then converted that or refactor it into a class-based application.

03:48:21

Well, to kick things off with this project, we are going to start by creating our application as a class-based application.

03:48:31

Let's begin here with all of our imports.

03:48:34

So from PIQT5 QT widgets, we have that one down.

03:48:40

Let's import our Q application.

03:48:44

We can import our Q widget.

03:48:47

What else do we need in our app?

03:48:50

So if we take a look at it, what do we see here?

03:48:53

I see Q labels.

03:48:55

I see Q line edits.

03:48:57

I see our Q combo box.

03:48:59

I see an area for our date and time.

03:49:02

We have a table.

03:49:03

A few new widgets.

03:49:05

We need to import all of these.

03:49:07

So let's begin.

03:49:09

I know that I'm going to have a Q label.

03:49:11

We saw a Q push button there.

03:49:13

We saw our Q line edits.

03:49:16

We can bring in our Q combo box.

03:49:19

Then our two new ones, we had a date edit window.

03:49:26

And finally, let's just come down here.

03:49:29

I'm going to say QTable widget.

03:49:34

Now I'm going to put that back on the line.

03:49:37

There we are.

03:49:38

QTable widget.

03:49:39

Anything else that we're missing?

03:49:42

Is there anything else we need?

03:49:44

Well, don't forget QV box and QH box.

03:49:48

Even if you don't know if you're going to need both layouts,

03:49:52

it's always good to import them because there's a high likelihood that you will.

03:49:57

Let's create our class.

03:50:00

Let's create a class called expense app.

03:50:05

Inside, we can create our constructor as this is going to run immediately.

03:50:11

Every time we create our app.

03:50:14

So when our program runs, it creates an instance from our object and this in

03:50:20

it constructor will immediately run.

03:50:23

We need to ask ourselves, what do we need?

03:50:25

Well, our main settings, we usually like to use resize.

03:50:30

But I don't have any main window.

03:50:33

And in order to get that, let's inherit just like we've done before.

03:50:38

Let's inherit QV widget.

03:50:40

Now that I have QV widget, I can refer to myself.

03:50:44

And we can say, okay, let's resize.

03:50:48

And let's give ourselves a window title because we always want to give our app a title.

03:50:54

We can call this expense tracker 2.0.

03:51:01

The window size, let's give it a size of 554 width and 500 for height.

03:51:07

That's a good starting point.

03:51:10

Now we need to create all the objects we see on the screen.

03:51:14

Remember the input fields, the table, the date box, all of those items.

03:51:20

So let's create one, let's say date box.

03:51:24

And date box will be one of our properties or an object that we're creating now for the app UI.

03:51:30

And at date box, we can say Q date edit, just like so.

03:51:35

We also have a drop down box, so let's just say drop down.

03:51:40

And this is our Q combo box.

03:51:44

We have our amount, which is going to be a Q line edit.

03:51:51

And then we have our description, an area that you can enter what you spent that money on.

03:51:57

And that will also be a Q line edit.

03:52:00

Now we did have text within the app, but that's going to create too many objects.

03:52:05

And the text, I won't need to do anything with that value, so I'll actually create it here when I create my design.

03:52:13

Speaking of design, we need to justify our master layout.

03:52:19

I can create my object master layout.

03:52:22

And I know that everything here will be held in a column, so let's say Q V box.

03:52:29

We have that.

03:52:31

And within that column, we are going to have, let's say row one,

03:52:37

row two and row three, bringing those down.

03:52:44

Just remember to change the name of your property.

03:52:49

All right, what else do we need?

03:52:51

We have our input fields.

03:52:53

I know I'm going to have a few buttons on the screen.

03:52:56

So our buttons will be an add button to be able to add to our expense, so we can say that will be a Q push button.

03:53:05

Add expense.

03:53:09

We will also have a delete button.

03:53:13

This delete button once clicked will remove from our table.

03:53:20

We have almost everything that we want to see.

03:53:23

This brings us to our final and our new object.

03:53:27

We are introducing SQL in this project.

03:53:31

So with SQL, I want to be able to display all my data within a table.

03:53:37

We are going to use our Q table widget.

03:53:40

Let's create a property called table.

03:53:43

This can be our Q table widget.

03:53:46

We can do a few things with this.

03:53:49

In the beginning, when I'm creating this table, let's take our object.

03:53:54

I would like to set the number of columns.

03:53:58

This will help us with our SQL queries and adding data at a later stage.

03:54:04

Let's use the method of set column count.

03:54:07

In here, I'm going to have five rows of data, which we will see here shortly.

03:54:13

But that's going to look like an ID, a date category, amount, and description.

03:54:22

That is why we have five columns.

03:54:26

Once we have this, then we can take our table.

03:54:29

I'm going to call the method set horizontal header labels.

03:54:35

Because I want to give a title to each column that we create.

03:54:39

This will actually take a list.

03:54:42

We can do this two ways.

03:54:43

I can say header names, making a list.

03:54:47

What do we want our header names to be?

03:54:50

Let me code these out.

03:54:51

I now have a list of my header names.

03:54:54

You can see these are my column names.

03:54:58

Just like before, I created five columns in column one.

03:55:02

That's my ID column, column two's my date.

03:55:06

Our method set horizontal header labels that takes a list.

03:55:10

So header names.

03:55:14

Did I have to make this?

03:55:16

No, I did not.

03:55:17

I could take this.

03:55:19

I could just put this inside here like this.

03:55:21

How I did it before was easier for readability.

03:55:25

We have a table now with five columns in the columns each have their own name.

03:55:30

We're ready to go.

03:55:32

What do we need now?

03:55:34

I have all my objects.

03:55:36

Next up in our code burger.

03:55:38

I can actually structure this.

03:55:40

So there we are.

03:55:41

We can design our app with our layouts.

03:55:44

What layouts will we be using?

03:55:47

QV and QH box.

03:55:50

Let's create a master layout.

03:55:53

That can be my QV box.

03:55:56

Then within my app.

03:55:58

I know that I'm going to have three rows.

03:56:01

So row one QH box layout.

03:56:04

Let's create the other two.

03:56:06

We have our master layout along with our three rows ready to go.

03:56:11

Now that we have these, let's go through and design.

03:56:15

Row one.

03:56:16

I want to start with you.

03:56:18

I want to add some widgets to row one.

03:56:21

And case we forgot what we're aiming for in our app.

03:56:25

In row one, I am looking for these.

03:56:29

Date text, the date time box.

03:56:32

Our category text and our QCombobox.

03:56:35

Notice I didn't actually make Q labels.

03:56:39

And that was to save us space in our code as we aren't going to do anything with these values.

03:56:44

So I can immediately add these to my layout.

03:56:48

What do I mean by that?

03:56:50

Well, right in here, I can just actually add the class Q label.

03:56:54

What is this going to say?

03:56:56

Well, it's going to say date.

03:56:58

Like that. So I've added my widget.

03:57:01

Next up in my row one, I would like to add.

03:57:04

What do we want?

03:57:05

Well, I would like to add my date box.

03:57:11

After these, we can add category text.

03:57:16

Followed by our QCombobox, which is what we call dropdown.

03:57:22

So row one is completed.

03:57:24

Going on to row two, it's the same idea.

03:57:27

I can take this as a starting template.

03:57:29

Instead of row one, change that to row two,

03:57:32

our Q label that we're going to be putting on,

03:57:35

which actually right here, this should also be our Q label.

03:57:39

Instead of saying date here, we can actually say amount.

03:57:43

What do we want to add next to amount?

03:57:45

Well, let's add the widget and let's say self dot amount.

03:57:49

That was our property that we created here of a Q line edit.

03:57:54

The final two.

03:57:57

All right, row two's completed.

03:57:59

Row three, we just want to add our two push buttons to them.

03:58:06

Great.

03:58:07

Our three rows are designed and all ready to go.

03:58:11

What does that mean?

03:58:12

What do we need to do with our rows?

03:58:14

Let's add the rows to our master layout.

03:58:17

So take your master layout.

03:58:20

Use the method add layout.

03:58:22

You should have this under your belt by now, adding in row one.

03:58:26

We can copy that as we need to do it three times.

03:58:29

One, two, get them all set.

03:58:31

The only thing we have to do is change the layout that we're adding.

03:58:35

So self dot row two, self dot row three.

03:58:39

Let's set our final design.

03:58:42

Usually, we would do something like this.

03:58:45

But where is my main window?

03:58:48

I don't have a main window.

03:58:50

Remember, my main window is my super class.

03:58:53

So I'm going to refer to my self.

03:58:56

I can say self dot set layout.

03:58:59

I want to set the master layout as the main layout.

03:59:03

All right.

03:59:04

Our design is almost all the way there.

03:59:08

Currently, there's no table on the screen.

03:59:11

We've added our three rows to the screen.

03:59:14

Then we did set the final design.

03:59:17

But right in between here, before I set my final design,

03:59:21

this is where we want to see our newly created table.

03:59:26

Let's add that.

03:59:27

But the table is so big.

03:59:29

I don't need it in a row.

03:59:31

It's going to take up the whole row itself.

03:59:33

It's just going to go at the bottom of our expense app.

03:59:37

All we need to do for this is take our master layout.

03:59:41

We can add widgets and we can add our table.

03:59:45

Because we have created our class-based application,

03:59:48

let's go on the outside right here.

03:59:51

And we can say if name in main.

03:59:56

We can create our app queue application.

04:00:00

Give it an empty list.

04:00:02

Here, you could create something just an object.

04:00:05

And what is our app class expense app?

04:00:09

Main.showapp.execute.

04:00:15

Let's run our app and see if it's set up the way we want it to be.

04:00:21

All righty.

04:00:22

So right in here, it's telling me that I need to activate my superclass.

04:00:26

Which, that's actually true.

04:00:28

I buzzed right over that.

04:00:30

Going up, remember, anything that we pass in.

04:00:33

So I'm inheriting the superclass.

04:00:35

Let's use the handy Python super function and say,

04:00:38

Hey, super, I want to initialize you.

04:00:41

Just like that.

04:00:43

Give our app one more run.

04:00:45

There, it's all taken care of.

04:00:47

Here is our app ready to go.

04:00:49

Everything is where we want it to.

04:00:51

In our three rows with our new table at the bottom.

04:00:55

Spend the next five minutes and tweak any details you may want to tweak.

04:00:59

If you want to change the words, change the header names,

04:01:03

change your alignment.

04:01:05

That's up to you.

04:01:06

I'll see you guys over in our next lesson,

04:01:09

where we will introduce sequel in Python.

04:01:13

Music

04:01:37

Now that your app is all set up and ready to go,

04:01:41

it's time to introduce the topic of sequel.

04:01:45

And how we are going to use sequel light with the module

04:01:49

Cutie sequel to work with our app in Python.

04:01:53

If you've worked with sequel before, great.

04:01:56

You have a head start.

04:01:57

And if you've never used sequel before, that's okay.

04:02:00

Because I've structured this lesson as a breakdown to what it is

04:02:05

and how we can use it.

04:02:07

It's going to ease you into working with sequel.

04:02:10

Let's jump in.

04:02:11

So sequel really means structured query language.

04:02:15

You might hear people say SQL or more commonly sequel.

04:02:19

Now we're going to look at three sequel keywords.

04:02:23

And this is basic syntax for sequel.

04:02:26

These words, these key operators, are used in the sequel language.

04:02:31

Select from where.

04:02:35

Notice that all of those are capitalized.

04:02:38

That's very important.

04:02:40

We use the select operator to select the column we want to look at.

04:02:45

We use the from operator to choose the table where the data lives that we're trying to look at.

04:02:53

And we use where to justify a specific condition.

04:02:58

So when something is true, that's what we want to find with our data.

04:03:05

So picture this.

04:03:06

We have an example down here.

04:03:08

Picture I have a table that has the name users.

04:03:12

I have two columns in my table.

04:03:15

I have a username column and a password column.

04:03:20

Then I have a condition that I want to look for the username Mario123.

04:03:28

I could write my query in two ways.

04:03:31

Up here I'm writing a query.

04:03:33

I'm saying select star which literally translated means select everything.

04:03:40

From my table, remember my table is called users.

04:03:46

So this literally says I want to select everything from the table named users.

04:03:53

But that doesn't do it right because I have a condition.

04:03:59

So I want to be more specific.

04:04:02

I'm looking for a username, right?

04:04:05

Well, select the column named username.

04:04:10

From the table named users, where my username is equal to Mario123.

04:04:21

That's allowing me to access key components of my database and pull out the data that we are looking for.

04:04:30

We are using SQL and we use this to work with our relational databases.

04:04:36

Or these are databases that store our structure data within tables.

04:04:42

Let's take a look at how we set up a SQL connection in PiQT.

04:04:51

Before I move on, remember these three key words from SQL, select from and where.

04:04:58

And try and remember these two examples and how they relate to our example here.

04:05:04

Let's take a look at how we can set up a SQL connection in PiQT.

04:05:09

In order to create a connection to SQL light, we are going to import something called QSQL database.

04:05:17

We can import this from QT SQL module.

04:05:21

I am adding a database.

04:05:24

What type of database is this? Well, it is a SQL light database, which is a lightweight database for working with SQL and Python.

04:05:34

I am justifying that as the value to a variable or an object of database.

04:05:40

I can give my database a name, giving it right here, making sure my extension is .db.

04:05:47

These are the methods that we are going to see here. I can use add database to create my connection.

04:05:53

I can use set database name to set the name.

04:05:56

And we are going to use the open function to open our pre-existing database, so that every time we load our app,

04:06:06

it is going to load all the data that we have previously stored in our database.

04:06:14

You can see I have a condition here. Now, let's just start with the very basics.

04:06:20

I have a database, so if my database is not open, I want to print off error.

04:06:29

I'm going to talk more about this in the next slide, but the key component here is I am creating a condition.

04:06:38

Just to make sure that indeed I do have a database and I can open it.

04:06:43

I don't have a database and I can't open it. I want to print off or alert the user to an error.

04:06:50

Now, you can see I am using something called Q message box.

04:06:55

Simply put, in Python, a Q message box is just a pop-up box.

04:07:01

Any of these pop-up boxes can look like the following.

04:07:05

You can see they are all different, but they are all little windows that can pop up on the screen.

04:07:10

And each method we use with Q message box. So for example, I want to ask the user a question.

04:07:18

You can see that it kind of has a question mark. Warning, warning, critical, critical.

04:07:26

They are different things that we are triggering.

04:07:29

We can use to ask the user questions as well.

04:07:34

And based on the response of the user, we can do something with those.

04:07:39

But let's focus on the bottom two right now because it's just a pop-up and it's just a learning the user to something.

04:07:46

Remember that those methods are linked to what type of Q message box we are seeing.

04:07:53

Now that we've created our connection to our database, remember from the previous slide, database was created and we open our SQLite database.

04:08:04

Let's create a query and we want to run our query to create a table named Expenses.

04:08:11

But we want to check first to make sure it doesn't exist.

04:08:15

So a query is basically a question that we are asking the database.

04:08:20

I'm preparing to query or ask the database for some type of information.

04:08:28

So I can create an object and I'm going to import Q SQL query.

04:08:34

This is used to execute any queries on our connected database.

04:08:40

Then I can use my query and I can execute a question or I can execute a query to my database.

04:08:51

This structure inside is actually quite important, okay?

04:08:56

All of this is a string and this is how we can use SQLite to perform queries and Python.

04:09:04

We are saying, hey, I want you to create a new table if it doesn't exist.

04:09:09

And I want you to name that table whatever you say here, Expenses.

04:09:15

We are giving an ID.

04:09:17

Now, these items here are the columns in our database.

04:09:24

So the first column is going to be the ID of that item in our database.

04:09:29

The second column is going to be a date.

04:09:32

And this date is going to be the value type of text category.

04:09:37

It's going to have a text value.

04:09:40

A mount is going to have a real value, a number value.

04:09:45

We use this execute method, which you've seen before in Python.

04:09:51

Because it prevents us from needing additional boilerplate code.

04:09:56

Specifically with SQL, we can incorporate the code inside the execute method.

04:10:03

So take a look at what's happening here.

04:10:07

We execute the SQL query specified in our quotation marks to make it a string.

04:10:13

And we create a table named Expenses with the following columns.

04:10:19

ID, date, category, amount, and description.

04:10:23

Each of those I'm also telling the database what type of data it's going to have.

04:10:30

Is it a text data or is it a number data?

04:10:34

Let's jump into our project and let's create a database that we can begin to add things to.

04:10:40

Where are we going to create our connection to the database and where will we create the query?

04:10:46

Those are questions to ask yourself as we jump onto the code.

04:10:50

I will see you guys in the next lesson.

04:11:00

Now that we have our database all set up, it's time to create our methods.

04:11:22

Now these methods will be building our specifically going to be built for our add and delete buttons.

04:11:29

When we click add, we want to add our data to a database.

04:11:33

When we click delete, we want to remove our data from our database.

04:11:38

Let's take a look at our first method.

04:11:41

Before we even get to the add and delete methods, we need a method for loading our table.

04:11:47

Because every time we open the app, we want to load our pre-existing data.

04:11:53

Now, in the previous projects, I've put a lot of code examples on the screen.

04:11:59

But at this stage, you should feel challenged or, at least, I want you to put in the challenge to problem solve,

04:12:07

and to logically solve these steps.

04:12:09

I have broken down step by step what we need to do to create the method to load the table.

04:12:15

And I am going to show you a part of the code in the next slide.

04:12:19

Start to think about how we can do it using what we talk about now.

04:12:23

The first thing we need to do is we want to clear the current table.

04:12:28

That's because any old data, I don't want the old data to be there.

04:12:32

To do this, we're going to look at something called set row count.

04:12:36

I can then create a new query to select everything from our table using our class QSQL query.

04:12:46

You'll create a loop in this loop will run as long as there are more rows in the table, right?

04:12:53

So, if you have a database with 10 rows or 10 pieces of data,

04:12:59

your loop is going to run 10 times until everything from your database is in your app.

04:13:06

Once we do that loop, we can retrieve the values from each column.

04:13:11

We will use the value method to do that.

04:13:15

The information we retrieve, we want to insert the data from number four, right?

04:13:20

That's what we've retrieved and we can use insert row to do that before increasing a row counter.

04:13:27

This method is responsible for displaying all of our database data in our app so we can visually see it.

04:13:36

How would the loop look?

04:13:39

I want to make a loop and that's going to repeat and I want to use a next method with a loop.

04:13:44

That's a bit odd. Well, along with our query, we do want to create a while loop.

04:13:51

So I can say, while there is another row in my query, that's what that translates to, right?

04:14:00

So while my database still has another row, I want my code to run.

04:14:08

Every time this loop runs, we are retrieving the values from each column.

04:14:15

column one, column two, column three, column four, column five.

04:14:21

If you have more columns, make sure you retrieve those values.

04:14:25

We're using the value method that takes an integer.

04:14:30

Once we've retrieved all the data from that current row from every column,

04:14:36

we want to insert that data into our table.

04:14:40

So imagine, your table is called expense table.

04:14:45

You want to insert the current row that you're on, right?

04:14:52

So row needs to be an integer.

04:14:55

We need to insert the current row.

04:14:57

We can then go through and set the items of every row.

04:15:02

So I'm going to put my row number, which would be the same for all of these.

04:15:07

And then I'm going to put the column in the row.

04:15:11

Next is the information we want in that row.

04:15:15

Now notice, this is a new class.

04:15:19

But this is the item that we collected that we want to display in row one,

04:15:26

or more specifically in the first column of our first row.

04:15:32

Now we're going to look at the added new expense method.

04:15:35

What do we want to do with this?

04:15:36

Well, we want to gather the info that we entered from the input boxes.

04:15:42

All the info, the date, the description, the drop down information, the amount,

04:15:48

and we want to insert all that information into our database.

04:15:54

Then we want the input fields to clear to prepare for the next input.

04:16:01

We can then load our database.

04:16:05

If I add or delete information, I want to load that new database information.

04:16:11

So we can visually see it.

04:16:13

Take a look at all these methods.

04:16:15

Some of them we've worked with before.

04:16:18

Others are new.

04:16:20

Which ones look familiar to you?

04:16:22

Do you remember why and how we used them in our code?

04:16:27

Let's take a look at what each of these will do for us.

04:16:30

I'm going to touch on a few of these.

04:16:32

I'm going to touch on all the new ones we have in a dress.

04:16:35

And if you need to pause the video screenshot, that's fine.

04:16:39

You can do that.

04:16:40

We have the prepare method.

04:16:42

We use prepare when we're working with SQL.

04:16:45

And this will check the provided query to make sure that it's a valid question.

04:16:50

It's a valid query.

04:16:52

So when we click a button, I want to check to make sure that all my data is going to sit well in my database.

04:16:59

That is when prepare comes in hand.

04:17:02

We have the method add bind value.

04:17:05

Add bind value will put the information in a column.

04:17:09

That's in our database for us.

04:17:11

Every piece of information we will need to use add bind value.

04:17:16

We can use the two string method and this will convert an object into a string.

04:17:22

We can use date and this will convert our input in our case, which is a date into an actual date.

04:17:31

And let's take a look at our last one here.

04:17:34

Current date.

04:17:35

This will get the live current date and time.

04:17:38

Like if I ask you, hey, what's the date today?

04:17:41

That is what that will return.

04:17:45

Take a look at these.

04:17:47

Remember, these are all methods.

04:17:49

So think about the objects that these will be linked to.

04:17:53

How can we finish up our add function?

04:17:56

Within our add new expense method.

04:17:59

The first thing I want to do when I click the add new expense button is we want to collect all the data from our input fields at the top of the app.

04:18:09

You can see I'm collecting my date.

04:18:12

I'm collecting the information from my drop down box, which is a category.

04:18:17

We are getting our amount and we're getting the description.

04:18:21

Using all this information that we just captured from the input fields, we can create a query.

04:18:30

And we can prepare to execute our query.

04:18:35

Now notice the SQL syntax.

04:18:38

Insert into.

04:18:40

So we can prepare to insert into our table expenses.

04:18:46

What do we want to insert?

04:18:48

Date category amount description.

04:18:51

Date category amount description.

04:18:53

Our information is going into our database.

04:18:57

Every item we want to send off that info now.

04:19:02

So prepare it's preparing to get the database ready to accept this new information.

04:19:09

Now we want to send off our information to our database.

04:19:13

And we can do that using the add bind value and giving it an argument.

04:19:18

What do we want to send?

04:19:20

Well, I want to send my date off to my query.

04:19:23

And you can see in position one of my query is the first item that we prepared as well.

04:19:31

In position two of the query is the second item we prepared for our query.

04:19:38

All right.

04:19:39

Let's go back to the escode and see if we can program out this add new expense method to make some SQL queries.

04:20:01

We have our app all set up and ready to go.

04:20:15

You've been introduced just on the surface to SQL.

04:20:19

And I'm excited to be able to implement that now into our application to create a real database that we can load in data, delete, and add data.

04:20:29

To begin, let's go to the bottom of our code.

04:20:33

Here we have our class at the bottom.

04:20:36

That's what's running, right.

04:20:38

This is where our app is running.

04:20:40

Right here, this is where we can create our database.

04:20:45

Before I can create the database, we need to import that from our module.

04:20:52

Going up here, all we currently have is PiQT and the QT widgets module.

04:20:59

We want more than this.

04:21:01

We are going to say from PiQT5.

04:21:06

The module we're looking for is QTSQL.

04:21:11

We want to import two classes or two modules from within.

04:21:15

I want the QSQL database and we would also like the QSQL query.

04:21:24

Those two, perfect.

04:21:27

Outside, while we're creating our database here, I can create a variable.

04:21:31

I'm going to call that variable database.

04:21:33

And I can say, all right, database is equal to QSQL database.

04:21:38

I want to add a new database.

04:21:41

What kind of database is this?

04:21:43

This is going to be a QSQLite database.

04:21:47

We have this variable that is a SQLite database.

04:21:53

We can take it and let's set the name.

04:21:58

The name I can call is expense.db.

04:22:04

You guessed it, stands for database.

04:22:07

We've created it.

04:22:09

I want to create and try and catch any errors that might happen.

04:22:13

The error that might happen is I'm not able to open my back end.

04:22:19

I'm not able to open this database for some reason.

04:22:22

If that happens, my app needs to close.

04:22:26

It's not able to open without any data.

04:22:29

Let's say if not my database open.

04:22:33

So if I can't open it, I want a message to appear in the screen.

04:22:38

How do we do that before?

04:22:42

What did we use?

04:22:43

It starts with a Q, but we haven't imported it yet.

04:22:47

Q message box.

04:22:49

Let's go in import Q message box.

04:22:52

At the top, right, there's our Q message box.

04:22:57

Returning now, I can create this.

04:23:00

And let's say critical, because if this happens, that is a critical error.

04:23:05

I can't get past that.

04:23:07

My app can't run without it.

04:23:09

Our first argument can be none.

04:23:11

I'm going to say error within the app.

04:23:14

I can say, could not open your database.

04:23:19

What do we want to happen?

04:23:21

I would like exit.

04:23:22

I want my app to just exit immediately.

04:23:25

Exit is something that we need from another module.

04:23:28

This is the only time we're really going to use it in our applications.

04:23:32

That module is called sis or system.

04:23:35

We want it to exit after one second.

04:23:38

Up at the top, let's pop in here, import sis.

04:23:42

Now that we've created this database, I can now create an initial query.

04:23:49

Remember, query is like a question or initial setup.

04:23:53

So how do I want to set up my database?

04:23:56

What structure is this going to have?

04:23:59

I will create a object called query from the QSQL query class.

04:24:06

I'm going to execute an initial query or run an initial query when this is ran.

04:24:14

This is where we put all of our SQL syntax.

04:24:18

A lot of this is specific for SQL light.

04:24:22

Here we're going to put six double quotes.

04:24:27

Drop down like that.

04:24:30

How do we want to set up this database?

04:24:33

Well, what I can say is I want to create a table.

04:24:38

If it doesn't already exist.

04:24:42

This table is going to be called expenses.

04:24:47

Or whatever you want to call that table, that goes there.

04:24:51

So if I don't have a table, I'm going to create one and it's going to be called expenses.

04:24:59

What structure will this table have?

04:25:02

If you don't remember, go up and let's take a look here at set horizontal header labels.

04:25:09

This is the structure of our database.

04:25:12

Let's make sure everything is pretty much how we want it.

04:25:15

I can say ID everything is capitalized.

04:25:18

The first thing that's going to be in my database will be ID that will be in column one and so forth.

04:25:25

Returning to our query, let's say the first one is our ID.

04:25:31

ID is going to take something called integer, primary, key, auto increment.

04:25:42

What this means is an ID, I'm not giving it that information.

04:25:47

Every new row of data, it's automatically generating a number.

04:25:52

So row one, row two, row three, and it's automatically adding in that number.

04:25:57

So that's auto increment.

04:25:59

This is known as the primary key, the master key for that row.

04:26:05

Let's put a comma.

04:26:06

Next up we have date.

04:26:08

What is date?

04:26:10

Well, date is going to be text.

04:26:14

We don't have to do anything mathematical with that value, so it's just text.

04:26:19

Next up is category.

04:26:21

Category is also text.

04:26:23

We have the amount.

04:26:24

A amount is real.

04:26:26

Real in the sequel just means it's a number.

04:26:29

We can do something with that value.

04:26:31

Lastly, we have our description.

04:26:35

And our description is text.

04:26:40

Great.

04:26:41

We have our query already to go.

04:26:43

It's set up in the order that it's going to receive that data.

04:26:46

It's going to receive it as an ID, but it won't receive that because that's automatically being incremented.

04:26:52

The other four in order are being added into this newly created database.

04:26:59

Every query is going to be structured in this order.

04:27:03

ID, date, category, amount, and description.

04:27:08

Amazing.

04:27:09

We've created our first database in the app.

04:27:12

But currently we can't do anything or we are not doing anything with it.

04:27:16

We want to be able to add and load from this.

04:27:20

Let's go up to our class.

04:27:22

We are going to create a few methods here.

04:27:24

The first method I want to create before I can add data or delete data.

04:27:29

I need to load my table into my app.

04:27:33

I need to load my database.

04:27:35

Let's create a method right here and let's say load table.

04:27:40

It's a method.

04:27:42

It's in my class.

04:27:44

It's after we initialize everything.

04:27:47

I can give ourselves a bunch of room right here.

04:27:50

To kick things off, let's take our table.

04:27:53

I'm going to take the table we've created.

04:27:55

And I'm going to set the row count.

04:27:59

We are going to set it at zero.

04:28:01

This is one of the methods we introduced during our lesson during the previous slides.

04:28:07

We have our row count set.

04:28:10

I can create a new query, a new question.

04:28:13

Remember, anytime I say query, I'm saying question.

04:28:17

What do I want to ask it?

04:28:19

I want to ask it to select everything from my table known as expenses.

04:28:30

Please remember that these are special SQL syntax words.

04:28:36

Expenses is lowercase because that's the name of my table.

04:28:41

Select is a word and from is a word from SQL.

04:28:45

Let's create a row.

04:28:47

Because currently, I haven't loaded in any data.

04:28:50

But I want to start on row zero and begin after that.

04:28:55

So row zero, row one, row two.

04:28:58

Everything after that first row will be loaded in as well.

04:29:01

But we need to load in the first row.

04:29:04

We can say, while my current query dot next.

04:29:08

So while I have another row available still, while there is another row in my table.

04:29:16

We want to get the values from each column in our row.

04:29:23

Remember the order of our column.

04:29:26

Let me bring back up our SQL query.

04:29:29

We have our ID date category amount description.

04:29:36

Let's go up now.

04:29:38

In order, let's get an expense ID.

04:29:42

Let's say the expense ID is just equal to our query value zero.

04:29:50

So it's equal to whatever the first column in my database is.

04:29:58

Because Python starts on zero, my first column is actually zero.

04:30:04

In my database, if you check, the first column is our ID.

04:30:09

So the value is whatever we get from our current row.

04:30:13

Next up, we can get a date.

04:30:16

We can say our date is query dot value.

04:30:19

And I think you can guess.

04:30:21

So for each of these, we want to get the value of that current column.

04:30:26

I'm going to go forward and I'm going to grab the values from each column.

04:30:30

I have our five columns, and I'm getting the value out of each of those.

04:30:35

So every query runs, we get the value from that column.

04:30:39

We've indexed.

04:30:41

Now that we have these values, we want to put them into our

04:30:46

Q table widget.

04:30:47

So I'm going to say add values to table.

04:30:52

We can't see these values.

04:30:54

We can't see what's in a database.

04:30:56

I want to take it out of the database and put it into a table for us to be able to see.

04:31:03

Let's take our table property, and we can say insert row.

04:31:09

What row do I want to insert?

04:31:11

Well, I want to insert the first row, which would be row zero.

04:31:15

The first time this while we runs.

04:31:19

But I need to be able to increment that to go to row two, row three.

04:31:24

I'm just going to put my row variable.

04:31:27

Remember, we have our row variable here, so I'm adding the first row.

04:31:32

I'm inserting the first row to my table.

04:31:36

At the end of this, you guessed it.

04:31:39

We can increase the row, so every time our loop runs,

04:31:44

we are increasing the row and adding in row two, row three, et cetera.

04:31:51

After we've inserted the row, I want to take the values that we got back.

04:31:56

And I want to insert them into a column within my table.

04:32:01

To do this, let's take our table.

04:32:04

I now have my table object.

04:32:07

And I want to set an item in that table.

04:32:11

Okay, what row is this from?

04:32:14

I don't know, but it's from the current row I'm on.

04:32:17

All right, now it's asking me for a column.

04:32:21

Great, the first one I know is column zero.

04:32:24

That's the first column.

04:32:25

Then we need an item.

04:32:27

Well, to get an item here, because we're working with a Q table widget,

04:32:33

I'm going to go up and I'm going to import one more key class for us to do this.

04:32:39

At the top here, let's import a class called Q table widget item.

04:32:45

This is an item in a table.

04:32:48

You guessed it.

04:32:50

Going down, I can now use that new class.

04:32:53

I can say Q table widget item, like so.

04:32:56

What is the first item in the first column?

04:33:01

Think about that for a moment.

04:33:03

What do I need to add inside here?

04:33:05

An ID.

04:33:06

Well, where's my ID?

04:33:08

It's right here.

04:33:09

It's called expense ID.

04:33:11

Let's convert this to a string and let's put in expense ID.

04:33:16

Just like that.

04:33:18

So I'm taking my table and I'm going to set an item in that table.

04:33:22

It's going to be in the first column and it's going to be my ID.

04:33:28

Amazing.

04:33:29

I'm going to copy this.

04:33:31

How many items do we have?

04:33:32

We have five.

04:33:33

So one, two, three, four, five.

04:33:36

There are our five items.

04:33:39

Let's go down.

04:33:40

Let's change our column numbers.

04:33:44

And also the values here.

04:33:47

What do we need here?

04:33:48

Well, I need a date.

04:33:51

I need my category.

04:33:54

I need my amount.

04:33:56

And amount is a number.

04:33:58

So I'm going to leave it to convert to a string here.

04:34:01

Our final one.

04:34:03

Our description.

04:34:04

If you need to pause to understand what's happening,

04:34:07

please do read through an interpret in your own way.

04:34:11

Once we're done here, I'm going to read through again and translate what's actually happening.

04:34:16

Let's bring our row up.

04:34:18

And we are ready to go through this method.

04:34:22

Let's break things up.

04:34:25

When this method is called, we are setting our table row count.

04:34:32

I'm then creating a new query.

04:34:35

I'm getting ready to ask my database a question.

04:34:39

What's my question going to be?

04:34:41

Well, I don't know yet.

04:34:43

But what I do know is I want to get the data to use for my query question.

04:34:49

I want to select everything from my table expenses.

04:34:55

I'm going to start with the first row.

04:34:58

And I'm going to repeat all of this while there is a next row in my database.

04:35:04

If there's not another row in my database, stop.

04:35:08

If there is a row, keep repeating.

04:35:10

Every time I loop runs, I'm taking the five values from the five columns in the current row.

04:35:22

I'm going to insert that row into my object table.

04:35:30

Remember, table is a cute table widget and I'm going to insert the current row that I'm on.

04:35:37

I then go forward and I set every column in my table to the items that I got earlier, those values.

04:35:47

We end with increasing our row.

04:35:51

We're pretty much done with our load method.

04:35:54

I'm going to go up here into our init.

04:35:57

I'm going to say here, I want this to automatically call load table method every time we boot up,

04:36:03

because we will always want to load in the database.

04:36:06

So I can insert that right there, self-load table.

04:36:09

Let's run our app.

04:36:11

Now we won't see anything because currently we don't have anything in our database.

04:36:16

Great.

04:36:17

Our app still works.

04:36:18

Airfree, which means we are ready to go to the next video.

04:36:21

In the next video, I will walk us through how we can add expenses to our database.

04:36:26

I'll see you in our next lesson.

04:36:33

We did a lot in our last video, and I hope you took some time to read through your notes and review the previous lesson.

04:37:01

As we introduced a lot more advanced concepts as well as introducing sequel and our databases to our project.

04:37:09

In the last video, you created a database as well as creating a method for loading in our existing database.

04:37:18

In this video, we want to be able to add items to this newly created database.

04:37:24

Wow.

04:37:25

I'm saying the word database quite a lot.

04:37:28

Let's go down to our load table method.

04:37:32

And right after it, we can create our add expense method right here.

04:37:38

The first thing that's going to happen in add expense is we want to retrieve all our input field data.

04:37:46

Let me show you what I mean.

04:37:48

I'm going to put past here for now.

04:37:50

Let's run our code.

04:37:52

Here's our app.

04:37:54

Let's say we have a date of today is the 8th, 23.

04:38:00

I have a category and amount, so 25, description, food, category.

04:38:09

Oh, I don't have a drop down box yet.

04:38:12

I have it, but it's not dropping down.

04:38:14

Let's address that too.

04:38:15

But all this information right here, I want to capture it.

04:38:19

It's like taking a picture.

04:38:20

I want to capture it and I want to store it in variables.

04:38:24

Remember that.

04:38:25

Let's go and address this drop down box quickly.

04:38:28

Going up our code, where did we?

04:38:32

We can jump in right here, actually.

04:38:38

So here we create the drop down.

04:38:40

Let's jump in here.

04:38:41

Let's say self dot drop down.

04:38:44

Let's say add items.

04:38:47

Add items takes a list just like the horizontal header labels.

04:38:51

What do we want the items in the drop down list to say?

04:38:55

Well, I want them to be our categories.

04:38:58

So pretend they are categories you could spend money on.

04:39:02

Food, transportation, rent, shopping, and entertainment.

04:39:15

Let's say bills and finally other.

04:39:18

So all of these are options that you can select from the box.

04:39:22

All right.

04:39:23

That should take care of that issue.

04:39:25

Let's do a double check.

04:39:26

Click that.

04:39:27

Yeah.

04:39:28

Okay.

04:39:29

Great.

04:39:30

So all this data here we want to capture this.

04:39:33

Returning to our add expense method now.

04:39:36

What we can do here is we can create four variables.

04:39:41

All the information we want to capture.

04:39:43

I know that I want to capture a date.

04:39:45

I have a category.

04:39:47

I have an amount.

04:39:49

And we have a description.

04:39:51

So these are all local variables.

04:39:54

I'm not making them properties.

04:39:56

They're only inside this method.

04:39:58

Date.

04:39:59

How do I capture the date?

04:40:01

Well, from what we looked at in the lesson when we introduced this topic.

04:40:05

We can capture the date by taking that date box.

04:40:09

So self dot date box.

04:40:11

I can convert the date.

04:40:14

And I want to turn that to a string.

04:40:17

What format do I want to format the date to?

04:40:22

That's going to be done here in a string as well.

04:40:25

I can say 1, 2, 3, 4.

04:40:27

That's a year.

04:40:28

So if it's 2,023, it will be 2,023.

04:40:33

Then I can do the month.

04:40:35

Then I can do the day.

04:40:37

That's how I want this format to look.

04:40:41

For my category, let's take our drop down box.

04:40:44

So self dot drop down.

04:40:46

Remember the method we used in our last project.

04:40:49

We can say current text to get the text value on the drop down box.

04:40:54

Item.

04:40:56

A mount.

04:40:57

Self dot amount.

04:40:59

We can say text.

04:41:01

You line at it.

04:41:03

We use the text method.

04:41:05

We saw this as well.

04:41:07

And we can get our self dot description.

04:41:10

That is also a Q line in it.

04:41:12

Getting a text value.

04:41:14

So we have four variables.

04:41:16

Each of these variables holds the value.

04:41:19

The face value of our items that we're trying to collect the data from.

04:41:25

We now want to take this.

04:41:27

And I want to drop it or put it into my database.

04:41:31

We need to create a new question for the database.

04:41:35

A new query for the database.

04:41:38

Let's say Q SQL query.

04:41:41

I'm going to prepare to ask it a question.

04:41:48

This is a SQL statement.

04:41:50

So our six quotation marks.

04:41:55

What do we want to prepare to do?

04:41:58

That's what this says.

04:41:59

Well, I'm going to prepare to insert into my table.

04:42:04

My table known as expenses.

04:42:07

What do I want to insert?

04:42:09

Well, I'm going to insert the date.

04:42:12

I'm going to insert the category.

04:42:14

I'm going to insert the amount.

04:42:17

Followed by my description.

04:42:22

Each of these that I'm going to insert.

04:42:25

So these are like the names.

04:42:27

Each of these are going to have corresponding values.

04:42:31

And these values will be represented by the information that we give it.

04:42:37

Currently, we don't know it, but the information we pass to it.

04:42:41

It'll have those four values.

04:42:43

We are preparing to insert into our table.

04:42:48

This information that we'll have four values as well.

04:42:54

We've prepared the query.

04:42:57

Let's now push or send information to our database.

04:43:03

So I can take my query.

04:43:06

And I can say add, bind value.

04:43:09

What value do I want to go into the first slot of the database?

04:43:15

I want the date.

04:43:18

You guessed it.

04:43:19

We can take this now.

04:43:20

One, two, three, four.

04:43:23

Next up in the second slot.

04:43:26

I want the category.

04:43:28

The third slot.

04:43:30

I'm out.

04:43:32

Fourth slot description.

04:43:34

We now have added these values to a specific column slot in our database.

04:43:40

I want my query to now execute.

04:43:44

It has the information it needs.

04:43:46

I want to send the information off to my database.

04:43:49

That is what we're doing with our query.

04:43:51

Once we've created that query, we captured all this information

04:43:55

from our box.

04:43:57

Well, I want to now clear those fields to prepare them

04:44:00

for the next expense that you might enter.

04:44:04

That's a convenient thing to do for the user.

04:44:07

Let's clear everything.

04:44:09

How can we clear everything?

04:44:10

This is a method we've used before in our previous projects.

04:44:14

Everything we do.

04:44:15

Let's start with our dropdown box.

04:44:18

Let's say dropdown.

04:44:21

We can reset it using this method set current index back to zero.

04:44:26

We can take our amount field.

04:44:29

And because that's a queue line edit, we can say clear.

04:44:32

We can take our description box.

04:44:35

And because that is also clear.

04:44:38

What am I missing?

04:44:40

Well, my date.

04:44:41

Now, my date originally was like one, one, zero, zero, zero, zero.

04:44:45

Let's say when it clears,

04:44:47

let's actually give the current date as the face value of our app.

04:44:53

That looks way better, too.

04:44:56

So let's take our date box.

04:44:59

And let's set the date of the date box.

04:45:02

I want to set the date to the current date.

04:45:07

To do this, we are going to import another module into our app.

04:45:13

This also comes from piqt5.

04:45:17

And it comes from a module that you're quite familiar with.

04:45:20

Let's say from piqt5.qt core.

04:45:24

I want to import a class called q date.

04:45:28

This will allow us to get the current date.

04:45:31

Let's return to where we were.

04:45:34

Inside our set date method.

04:45:36

What do I want to set the date to?

04:45:38

Well, I'm going to take my q date.

04:45:40

That's a class.

04:45:41

But I'm not giving it any arguments.

04:45:44

I just want to link it.

04:45:45

I want to link it to something called current date.

04:45:49

Just like that.

04:45:51

That is going to change the value of that date box to the date today.

04:45:55

And as of today, it is July 8th.

04:45:58

Amazing.

04:45:59

The last thing we want to do.

04:46:01

What do you think we want to do after we add an expense?

04:46:04

The last line of code.

04:46:06

Well, I have new information.

04:46:09

So I want to now load this new database.

04:46:13

I'm going to call the method we first made load table.

04:46:18

As I have new information in our database.

04:46:21

Great.

04:46:22

I'm excited.

04:46:23

Let's give our app a run.

04:46:25

At this point, we have the ability to add information to this table.

04:46:30

Before running the app, break down and pause.

04:46:33

What is happening here?

04:46:35

Let me go through and translate this.

04:46:38

When we click the add expense button.

04:46:41

So we need an event first.

04:46:44

But when we do click it, we capture all the data from the input boxes at the top of our code.

04:46:52

We capture a date.

04:46:55

We capture the current text.

04:46:58

The amount and the description.

04:47:01

Then I'm preparing to ask my database a question.

04:47:06

Or preparing a query.

04:47:08

What am I preparing to do?

04:47:10

Well, I'm preparing to insert something into my table that we named expenses.

04:47:16

I'm going to insert in the format date category amount description.

04:47:22

Each of these will have a value.

04:47:25

They have four values because I have four columns in our database.

04:47:30

Then in my query in the order that we said we're going to give it the information.

04:47:36

We are adding a binding value that's going to bind with that current query.

04:47:42

Once we add all the values, we want to execute and send the query off to our database.

04:47:48

We've added something to this database.

04:47:51

It's now time to prepare our app for the next input.

04:47:55

So we want to reset everything, finally ending with loading our new database into our table.

04:48:04

In order to get this to work, let's link this to our add button.

04:48:09

Where did we create our add button?

04:48:11

Up top.

04:48:12

Let's go up top to where we made the add button.

04:48:15

And right after here, we could just say, okay, self dot add button dot clicked.

04:48:21

When that's clicked, we want to connect to our new method add expense.

04:48:27

All right, time to run the code.

04:48:30

Let's give it a run.

04:48:32

Things are starting off.

04:48:34

Let's start things off with our date today.

04:48:36

So let's say 8, 7, 23.

04:48:41

Today, food, amount, 10, description, tacos.

04:48:46

Add, look at that.

04:48:49

We have added something into a database and taken that database and loaded it into our app.

04:48:55

Let's go for another one.

04:48:56

This time, let's say rent.

04:48:58

Let's say someone's rent is 500.

04:49:01

Let's say description landlord.

04:49:04

Add.

04:49:06

Oh, we have the ability to add things.

04:49:09

This is great.

04:49:11

We can say night out.

04:49:13

When did we do this night out?

04:49:15

Let's say one.

04:49:17

Amazing.

04:49:18

We have almost full functionality of our app.

04:49:22

The last things we need to do is program our delete button and any designs we want to do.

04:49:28

Well done.

04:49:29

I hope you're starting to see the gears turn and how we can use SQL to enhance our applications.

04:49:36

It's a way for us to store data within a database and pull it as we need it.

04:49:42

I'll see you guys in our next lesson where we will introduce the delete expense method.

04:49:59

Here you are in the final stages of your app.

04:50:07

And very well done because you've been introduced to a big new topic and you've only just scratched the surface.

04:50:13

What was that new topic that we've learned in this project?

04:50:16

Well, SQL, the structured query language that we use while interacting with databases.

04:50:22

And you've gotten it down so far.

04:50:24

Let's finalize this app.

04:50:27

This left to do.

04:50:28

Well, our delete function.

04:50:31

Our delete and expense.

04:50:32

What do we need to do to achieve this?

04:50:34

Well, in order we want to get the row that we clicked on from our table.

04:50:40

Remember this method?

04:50:41

We've used this before.

04:50:43

So whatever row we click on.

04:50:45

I want to capture that.

04:50:47

And I do want to check.

04:50:48

I want to run a quick check.

04:50:50

And I want to check to make sure that I indeed chose a row within that database.

04:50:56

If I did, I can create a variable using the ID of the row that I selected.

04:51:04

We can generate a question pop-up and we can ask the user if they want to delete.

04:51:11

Yes or no.

04:51:12

Remember the queue message box?

04:51:15

Well, we're going to use that here along with the question method.

04:51:19

If I choose yes from my pop-up box,

04:51:24

I can prepare a query.

04:51:27

And I want to see, well, syntax delete from table where the ID I collected is equal to the value.

04:51:40

We can then load in our new table using the load method that we previously made.

04:51:47

If we look at a little bit of the code from our delete method, you can see in the first part.

04:51:52

I am creating a variable.

04:51:55

And the value of this variable is whatever row we click on.

04:51:59

I am capturing it.

04:52:02

From whatever row I click on.

04:52:04

I want to get the ID from that row.

04:52:08

So, I'm saying my ID, this new variable,

04:52:12

is equal to my expense table item.

04:52:18

The selected row column 0.

04:52:21

Because I know that no matter what, every row in the first column, which is column 0,

04:52:29

that has actually holding the ID of that row.

04:52:33

So, I am selecting.

04:52:35

So, if I click on row 5, I want to go to row 5 and get the information that's in the first column

04:52:45

and convert that to text.

04:52:48

That's our ID.

04:52:50

Based on that ID, I'll now create a new query.

04:52:54

And I'll say, hey, prepare to execute this query.

04:52:59

All right, I want to send my message and I want to execute the query.

04:53:04

So, my expense ID is right here.

04:53:08

That's our question.

04:53:09

It's going to remove that row and load in our new database.

04:53:14

Right?

04:53:15

This prepare query, where is preparing?

04:53:18

Let's translate that.

04:53:20

It literally says, delete from my table named expenses.

04:53:25

But only where the ID matches the one I give you here.

04:53:32

That is how we could program out our delete method.

04:53:35

If you want to try and implement this yourself, jump on over to VS code.

04:53:39

And I'm about to head over there myself.

04:53:41

I'll see you over in VS code.

04:53:43

Let's finish off our app.

04:54:02

You're closing in on the final details of your project.

04:54:06

The last thing we should be doing is adding our delete expense method.

04:54:10

We have our functionality down.

04:54:13

We want to have the ability to remove something from our database from our app table.

04:54:19

Let's head down to our class.

04:54:22

And after our add expense method, this is where we focused our endeavors last lesson.

04:54:28

Let's create right here our closing method.

04:54:32

This will be our delete expense method.

04:54:37

Let's clean this up a bit.

04:54:39

So I'm going to give some space.

04:54:42

What do we want to happen?

04:54:44

How can we delete something?

04:54:46

Well, what I want to try to do is I'm going to click a row in my database.

04:54:52

And I want to capture whatever row I click.

04:54:57

I want to delete that row.

04:54:59

Whatever row we click on after I click my delete button.

04:55:03

We have within our UI design.

04:55:06

So for whichever row I click on I want to capture the ID that's linked to that row.

04:55:13

And I want to delete it from my app screen as well as my database.

04:55:18

Let's start with I want to capture the row that I click on.

04:55:24

Let's create a variable called like selected row.

04:55:28

This is equal to my table.

04:55:32

Do you remember how do we get the value of the row we clicked on?

04:55:37

We've done this before actually and we did this in our last project.

04:55:41

I'm going to say current row.

04:55:45

So the value of this variable is one of the rows that I click on in my table.

04:55:53

First things first.

04:55:55

I need to make sure that my database is not empty.

04:55:59

Because if I click into an empty table if there's no database or there's no rows,

04:56:05

I should not be able to delete anything.

04:56:07

So I need to anticipate that.

04:56:09

Someone might try to do that.

04:56:11

Let's make sure that if the selected row is equal to negative one.

04:56:18

So that means you actually did not choose a row from the table.

04:56:23

You're clicking the delete button but you did not click a row yet.

04:56:28

I want to alert the user to a problem and error.

04:56:32

What is the best practice for us to alert the user?

04:56:36

Let's give them a friendly message box.

04:56:40

And let's just give them a nice warning and say hey,

04:56:43

something's going on here and you might want to address that.

04:56:47

So that's a part of myself.

04:56:49

And I'm going to say no expense chosen.

04:56:53

You are the chosen one.

04:56:55

You didn't choose one.

04:56:56

So we can say that.

04:56:57

And I'm just going to say hey, please choose an expense to delete.

04:57:03

That looks nice.

04:57:04

Exclamation point.

04:57:06

We can simply then just return that.

04:57:08

That's going back to the user.

04:57:10

Nothing else is going to happen.

04:57:12

We now have checked and warned the user that they need to choose a row.

04:57:17

If they've chosen a row, we want to capture the ID from that row.

04:57:23

So specifically the text value of that ID.

04:57:27

Let's create a local variable.

04:57:29

And previously, we have one called expense ID.

04:57:32

I can use that here because this is within my method.

04:57:35

Expense ID is going to be a number.

04:57:38

Now the number is going to be something from my table.

04:57:43

And it will be one of the items in our table.

04:57:46

What item do I want from the table?

04:57:49

Well, I want to get it from the row that I've clicked on.

04:57:54

And I want it to be from column one, which is column zero.

04:57:59

Remember, in our database, the first column is our ID.

04:58:05

That's what I'm capturing.

04:58:07

I'm getting the ID from our database from the table specifically.

04:58:13

Everything in the table is a text object.

04:58:17

So I'm just going to say text here.

04:58:20

This whole item is an ID text value.

04:58:24

But we are converting it to an integer, which is good.

04:58:30

I have an ID.

04:58:33

Let's double check and make sure that that user really wants to delete it.

04:58:38

Because if they don't, then okay, let's give them a second chance.

04:58:42

Let's create and let's say something like confirm.

04:58:46

Confirm is going to be also a friendly message.

04:58:51

But this is going to be more like a question.

04:58:54

Because I want to make sure and I'll say, okay, are you sure that you want to delete this?

04:58:59

So we can say, are you sure?

04:59:01

Question?

04:59:02

What do we want to say then?

04:59:04

We can say delete.

04:59:06

Then we need to give them two options.

04:59:08

And it's telling me to give them two buttons.

04:59:10

Now these are going to be our queue message buttons.

04:59:12

So we can say the options are going to be queue message box.

04:59:17

It's going to be yes or no.

04:59:22

I can say that like that.

04:59:25

So I'm going to confirm.

04:59:27

And this little question box, which we've looked at before, is going to pop up.

04:59:31

And it's going to ask the user if they want to delete an expense.

04:59:35

The user will then be given two options from which they must choose.

04:59:40

Yes or no.

04:59:42

If our answer, so if what we get back from confirm, is equal to no.

04:59:50

What do we want to do?

04:59:52

Well, I just want the program to end.

04:59:54

I don't want to delete anything.

04:59:56

Here's a pop up box.

04:59:57

If the confirmation is no, just exit out of this method.

05:00:02

I'm done using it.

05:00:03

I don't want to do anything.

05:00:04

I don't want to delete that item.

05:00:07

But if this condition is not true, it means we do want to delete an item.

05:00:11

And we click yes.

05:00:13

What do we need to do to remove an item from a database?

05:00:18

Well, it's kind of the same question.

05:00:20

What do you need to do to create a database to add an item to delete an item?

05:00:26

We need to ask a question.

05:00:29

I'm going to prepare a query.

05:00:31

The query that I'm going to prepare is I'm going to take this query.

05:00:36

And I'm going to prepare something.

05:00:39

What SQL syntax do we want to use?

05:00:42

Well, I want to delete from my table called expenses.

05:00:49

Everywhere where the ID is equal to the bind value I give it.

05:00:58

What's the bind value?

05:01:01

Well, the bind value is going to be the expense ID.

05:01:07

This expense ID that we got from the row we clicked on is going to be where the ID matches that.

05:01:15

So, delete from our table everywhere where the ID is equal to the row we clicked on.

05:01:24

That's us using the add bind value again.

05:01:28

Finally, let's execute our query.

05:01:31

It's time to run it.

05:01:32

Now that we have new data, let's load our new table,

05:01:37

the updated version of our table into our application.

05:01:41

This pretty much wraps it up.

05:01:43

The final step that I'm going to put on here before a quick test,

05:01:47

going up to our buttons.

05:01:49

We just need to connect self dot delete button dot clicked dot connect.

05:01:55

We can link our delete expense method.

05:02:00

Are you ready for this?

05:02:02

Let's see if our expense tracker is ready to go.

05:02:05

Running our app lets choose.

05:02:08

So, you can see here my app's loaded and it's loaded in our saved database.

05:02:14

That's the point of the database.

05:02:15

We can save information.

05:02:17

Every time the app fires up it's loading that in.

05:02:21

Now, let's say I want to delete this rent.

05:02:24

That was an error.

05:02:25

So, I'm going to click.

05:02:26

I could click anywhere in this row.

05:02:28

I'm capturing the current row.

05:02:30

Delete expense.

05:02:32

Do I want to delete it?

05:02:34

No.

05:02:35

Okay.

05:02:36

So, nothing happened.

05:02:37

Entertainment.

05:02:39

Delete.

05:02:40

Yes.

05:02:41

Look.

05:02:42

Talkos.

05:02:43

That was a mistake.

05:02:44

Yes.

05:02:45

You can see our database working.

05:02:48

Look at that amazing.

05:02:51

Well done to everyone.

05:02:54

I'm so happy with how far we've come and how many projects we've been working through.

05:02:59

You started off with not knowing what this new framework was.

05:03:03

But now, you've come so far and you've learned how we can use this framework.

05:03:08

Pyt to build out windowed applications and Python.

05:03:12

And we're not done yet.

05:03:13

There's more projects to come and more tools that you're going to learn.

05:03:17

I will see you in our next video.

05:03:20

You've just finalized your expense tracking app.

05:03:49

We're at a later stage in this course.

05:03:51

And you may be wondering, okay, how can I start to implement a bit more styling into my apps?

05:03:58

This could be changing colors or adding boxes.

05:04:02

Anything like that.

05:04:04

In the next few minutes, you're going to learn how we can style our Pyt apps with CSS.

05:04:10

What is CSS?

05:04:12

You may have seen this term before.

05:04:14

You may have actually used CSS as well.

05:04:18

Let's take a look.

05:04:20

Now, CSS is used to style websites.

05:04:25

Specifically, it's used with HTML and JavaScript.

05:04:29

And it can be used with other languages and this also includes Python.

05:04:34

How does CSS work?

05:04:37

Well, our cascade styling sheet, that's our abbreviation, CSS.

05:04:44

We use it to target specific elements in our code.

05:04:50

So, for example, if you have a website that has H1 elements, these H1s are the big text, the headers.

05:05:00

I want to target all the H1 elements.

05:05:04

And I want to give them the font size of 32 and the font family gothic.

05:05:11

So, I can use these parent elements to target specific objects on my page or in our app and apply filters or apply stylings to them.

05:05:25

In CSS, we have our main elements, which are like your H1 tags, any of your header tags, your paragraph tags, anything like that.

05:05:37

You can also narrow it down.

05:05:40

So, if you created a class in HTML, you can target the class by using the dot with your class name.

05:05:50

Now, keep in mind, this only works for HTML in this class structure.

05:05:54

As in Python, we have something different.

05:05:57

And finally, you could style it by ID and ID is very specific.

05:06:03

So, I've actually put this in the order it takes precedence with our least important in between in the most important.

05:06:12

We can use our styling CSS by targeting our element followed by a set of curly braces.

05:06:22

Inside the curly braces, we put the font styles we want to apply to that element.

05:06:31

What would this look like in Python QT?

05:06:34

Well, it's actually going to look very similar.

05:06:38

We can style the same way in Python QT.

05:06:42

We just need to use the set style sheet method.

05:06:47

Inside here, the only difference is all of our styling is actually a string.

05:06:54

And you can see I've specified that by using a multi-line comment or a multi-line string with three quotes in the beginning and at the end.

05:07:05

What elements are we trying to target?

05:07:08

Well, remember, with CSS we are targeting the parent elements.

05:07:13

Originally, these were our main elements and classes.

05:07:18

Well, we can target that with Python QT.

05:07:22

You can see here, I want to apply a background color to my entire app, my finance class.

05:07:30

This will apply a solid background color to everything.

05:07:34

Everything that is a Q label, a Q line edit, or a Q push button, they are going to have these styles.

05:07:44

Then my QT review could have this style.

05:07:50

Now, we haven't talked about QT review, but don't worry.

05:07:54

I'm just including classes here as examples, but we will see these at a later stage in our course.

05:08:01

Let's jump back into VS Code and let's finalize and style our app.

05:08:07

I'll see you guys in the next video.

05:08:14

It's time to add some styling to our application.

05:08:29

Our current application is looking like this.

05:08:33

Let's take a look at what we're actually going to achieve in this video.

05:08:37

I want to take our application from this, all the way to something that looks like this.

05:08:42

Now, when you can use your own colors, of course, this is just going to be what I'm aiming for.

05:08:48

And we're going to do a little bit more than just CSS.

05:08:52

I have some bonus surprises we haven't talked about in an order to tweak our app.

05:08:57

But don't worry, as we go through, I will break it down and give you a good explanation.

05:09:03

All right, let's move these off and jump into our code.

05:09:10

At the top of our code, I'm going to go in here and let's just import Qt.

05:09:15

The first thing I noticed was when our app started, we don't actually have the initial date set.

05:09:23

So let's take our date box and let's call Qt.

05:09:28

We've actually done this before and we can link our current date method to our class Qt.

05:09:36

Now when the app starts, it's going to have today's date on it.

05:09:41

Okay, next up, I want to go down here to my table.

05:09:45

I want to design my table a little bit more.

05:09:48

There's currently a few things I don't like going on.

05:09:51

Let's bring our app back up.

05:09:53

In our app, I don't want to see this bar at the bottom.

05:09:57

I don't want to move the table. I want it to be hard-coded.

05:10:00

So how can I prevent that?

05:10:03

We are going to take a look at that.

05:10:05

And then another thing I want to do, for example, if I add this expense,

05:10:11

I want it to go in descending order.

05:10:14

So at the top, I have my newest entry, my newest expense,

05:10:19

and it goes down to my oldest expense.

05:10:24

Let's try to implement those two functionalities.

05:10:28

The first functionality here, I'm going to take my table.

05:10:32

I'm going to say self.table.

05:10:34

And I'm going to take horizontal header.

05:10:37

I want to apply a method and I'm going to say set,

05:10:39

section, resize mode.

05:10:43

This is going to allow our table to be hard-coded

05:10:47

and take away that scrolling bar.

05:10:49

So it's going to look nicer and more clean.

05:10:52

Within here, we need to stretch the header.

05:10:57

I need to stretch the table.

05:10:59

So to stretch the header, I'm going to use something called

05:11:03

Q header view.

05:11:05

We haven't imported this yet, but it does have a method called stretch.

05:11:10

Let's go up.

05:11:11

I'm going to throw in here and I'm going to say,

05:11:14

Q header view as a Q widget.

05:11:16

There we go.

05:11:17

So this is going to stretch our header across our entire table widget.

05:11:24

Brilliant.

05:11:25

The last little tweak I want to do to my table

05:11:28

is I want to sort them, so everything is in descending order.

05:11:33

Let's take our table.

05:11:35

And thankfully,

05:11:36

PICUTI has an awesome method called sort by column.

05:11:41

And inside sort by column,

05:11:43

it's going to take the column we want to sort.

05:11:46

So if you remember in our app,

05:11:49

the first column is actually our ID.

05:11:53

I want to sort the second column.

05:11:55

This is at position one.

05:11:58

So inside here,

05:11:59

I'm going to put one as I want to sort by column one.

05:12:02

And then my sort order,

05:12:03

I'm going to use QTI,

05:12:05

and I'm going to say D-sending order.

05:12:08

Now that we've styled that,

05:12:10

it's now time to add in some of our CSS.

05:12:12

Let's clean this up.

05:12:14

I'm going to add in my CSS before we add everything

05:12:18

to our design.

05:12:19

So let's say self dot set style sheet.

05:12:24

Inside here,

05:12:25

remember we need our string,

05:12:27

1, 2, 3, 4, 5, 6,

05:12:30

then we can add in our CSS.

05:12:33

What do we want to change?

05:12:35

Well, I want to change a few things.

05:12:37

In order to change my entire app,

05:12:40

we need to remember that our entire app

05:12:43

is actually a Q widget.

05:12:45

So I want to affect that parent element of Q widget.

05:12:50

Returning to set style sheet,

05:12:53

let's say, okay, so Q widget,

05:12:56

I would like to apply some styles to.

05:12:59

I'm going to give them a background color.

05:13:03

And the background color I want to be,

05:13:05

I have picked out is this.

05:13:07

Great, we have that color.

05:13:09

What else do we want to add in our Q widget?

05:13:12

Well, I have my Q widget.

05:13:14

Let's say we want to affect our Q label.

05:13:17

We could affect our Q line edit.

05:13:22

If we want to affect more than one element

05:13:25

with the same styling,

05:13:27

I can put a comma.

05:13:28

So in this line,

05:13:30

I'll be affecting any Q line edits we have.

05:13:33

Any Q combo box.

05:13:36

Q date edit,

05:13:38

as well as any Q push buttons.

05:13:41

We can have our Q table widget.

05:13:52

Q push button.

05:13:54

And then the last one,

05:13:56

we are going to apply a state.

05:13:58

So for example with CSS,

05:14:01

I could apply a hover state or other types

05:14:04

and to do this, I can use a semicolon.

05:14:06

And I'm going to say, okay,

05:14:08

when the Q push buttons are hovered over

05:14:11

with our mouse,

05:14:13

then these styles will be applied.

05:14:16

I'm going to go through,

05:14:17

and I've already created some styling

05:14:19

that I'm going to add in here.

05:14:20

Let's see what we're going to add.

05:14:22

My styling's look already to go.

05:14:24

Let's walk through and see what I've done here.

05:14:26

So I've taken my Q label and my Q labels

05:14:29

are going to have a darker font to them

05:14:32

and I'm setting their font size.

05:14:34

Anything that's text, Q label.

05:14:37

All of my Q line edits,

05:14:39

combo boxes in the date edit box.

05:14:41

They are going to have a background color

05:14:43

of this.

05:14:44

The text within those boxes will be this dark gray.

05:14:49

And I'm giving them all a border

05:14:52

around the perimeter of that object

05:14:55

with a little padding.

05:14:57

My table widget will be the same color

05:14:59

as mine over all background.

05:15:02

And it will have a border

05:15:04

so we will be able to see the difference between the two.

05:15:07

In between each row and column,

05:15:10

I'm going to have white,

05:15:12

or like this grayish color.

05:15:14

I'm applying my Q push buttons

05:15:17

which will be green with white text, no border.

05:15:20

Then when we hover over the button,

05:15:23

the color is going to change ever so slightly.

05:15:27

So a little bit darker.

05:15:30

Wow.

05:15:31

Look at all the styling.

05:15:32

So we can do that within one method,

05:15:35

cell.set style sheet.

05:15:38

This looks great.

05:15:39

Let's try running our app

05:15:41

and seeing our end result.

05:15:43

Is it what we're aiming for?

05:15:45

Amazing.

05:15:46

It is exactly what I was going for.

05:15:48

And you can see as I hover over these buttons,

05:15:51

they're changing color.

05:15:53

All of our items match the background color.

05:15:56

And I'm hoping that you used some of your own colors too.

05:16:01

Let's add our expense.

05:16:03

Everything is working.

05:16:04

How we want it to.

05:16:06

Delete.

05:16:07

Look at that.

05:16:08

Even our Q message boxes are styled

05:16:11

to what we set.

05:16:13

This looks amazing.

05:16:14

Incredible job.

05:16:16

Have a play around with CSS

05:16:18

and do a little bit more research.

05:16:19

Because in our next app,

05:16:21

you're also going to use CSS to do some styling.

05:16:24

I'll see you in the next video

05:16:26

for an introduction into our next project.

05:16:44

Our you guys ready for our next project?

05:16:57

Because I certainly am.

05:16:59

We are about to dive in and create an

05:17:01

interest rate calculator application.

05:17:04

In this application, you will be using everything you've learned so far.

05:17:08

But in order to create this,

05:17:10

we need a way to visualize data in Python.

05:17:14

We will introduce a library used for data visualization

05:17:19

in this project.

05:17:21

Let's break it down.

05:17:22

Here is an initial overview of our app.

05:17:26

Take a look at what we see going on

05:17:29

and what this app can really do.

05:17:32

We have the ability to enter

05:17:35

and interest rate the initial investment

05:17:38

or the amount of money that we want to put in.

05:17:41

And the number of years we want to invest for.

05:17:44

You can see up here,

05:17:46

here is the interest rate,

05:17:48

here is the initial investment,

05:17:51

and then here is the number of years we want to invest for.

05:17:55

You can also see that I have a little box here

05:17:58

for dark mode,

05:17:59

which is a way that we can style our application even more.

05:18:04

We can create a chart.

05:18:06

We are going to display in a table

05:18:09

or some type of view

05:18:13

all of our interest rates calculated.

05:18:16

And then finally, I want to have the ability to save.

05:18:19

So when we click this button,

05:18:21

I want to save our chart,

05:18:24

but then I also want to save our table as a CSV file.

05:18:29

What widgets do you see on the screen right here?

05:18:33

Well, we know all these, except queue-tree view.

05:18:37

This is going to be a new widget, a new class,

05:18:41

which allows us to have.

05:18:44

It's almost like a queue list widget,

05:18:46

but we have two lists going on.

05:18:50

We have two columns.

05:18:52

We have a year, and we have a total.

05:18:55

Then we do need something for our chart,

05:18:59

but just for the initial setup and design,

05:19:03

for now, let's just use queue label.

05:19:06

Very similar to what we did in our image editor app.

05:19:10

Are you thinking about your layouts

05:19:12

and how you're going to design this app?

05:19:15

A lot of things are happening here.

05:19:17

What makes sense to you?

05:19:19

What is the easiest way we could design this?

05:19:22

Are we going to have a master row or a master column?

05:19:26

And what will be inside our master layout?

05:19:29

What I've come up with is I've said that I could have two rows

05:19:34

because at the top of our app, we have a lot going on up here.

05:19:39

So this could be held in its own row.

05:19:42

Then I could structure it in a second row

05:19:46

and within the second row I can have two columns.

05:19:50

My first column is going to hold my queue-tree view

05:19:54

along with our buttons.

05:19:56

And my second column is just going to hold the area with the chart.

05:20:02

This for now can be our queue label.

05:20:05

Our design will have two rows,

05:20:07

row two will have two columns.

05:20:11

And together, row one and row two,

05:20:14

these will be held in our master layout.

05:20:18

That master layout, we can drop that into a column.

05:20:22

Start thinking about this

05:20:24

because you're about to head off and design the app on your own.

05:20:29

So based on your experience with PiQT and everything you already know,

05:20:34

how can we set up this app to the best of our ability?

05:20:37

I'll see you guys in the next video where together

05:20:40

we will prepare the initial layout and design of our app.

05:20:54

Alright, here we are in the initial setup for our interest rate calculator app.

05:21:14

You know what to do here.

05:21:16

Building on all the knowledge we have been learning.

05:21:19

How can we set up our initial project?

05:21:23

Let's kick things off with our imports.

05:21:27

What do we need?

05:21:28

From PiQT-5, we are going to do our QT widgets.

05:21:34

Import everything we want.

05:21:36

So queue application, queue widget.

05:21:40

What else are we going to be needing for our application?

05:21:44

Well, we need our queue labels.

05:21:47

We need our queue push buttons.

05:21:49

Let's get our layouts in there before I forget them.

05:21:52

So queue V box layout, queue H box layout.

05:21:56

We will use queue tree view.

05:21:58

That's the new widget item.

05:22:00

We have our queue line edits.

05:22:02

So I can say queue line edit.

05:22:04

And finally here, I'm going to talk about something briefly called queue main window.

05:22:10

Let's put that in as well.

05:22:12

And this will allow us to create a window.

05:22:15

Very similar to what the queue widget does.

05:22:19

But it allows us to inherit it a little bit differently.

05:22:24

Great.

05:22:25

I am then going to go and I'm going to import something else.

05:22:28

So I'm going to go to QT GUI.

05:22:30

I would like to import queue standard item model.

05:22:36

This is what will allow us to build out and add elements to our queue tree view itself.

05:22:44

Great.

05:22:45

We want to create a class based application.

05:22:48

So I'm going to create one called finance app.

05:22:51

And instead of inheriting queue widget this time,

05:22:55

I'm going to inherit the main window itself.

05:22:59

So let's say queue main window.

05:23:01

You've seen how we can inherit queue widget.

05:23:04

The same thing is going to be done here for main window.

05:23:07

And it's going to act very similarly.

05:23:10

Let's create our constructor.

05:23:12

What do we want to run when the app first starts?

05:23:16

Well, everything actually.

05:23:19

Of top here, I can inherit.

05:23:22

And so let's say our super function.

05:23:24

I want to inherit everything from our finance app.

05:23:29

And I'm just going to say in it.

05:23:31

Just like that.

05:23:32

So I'm inheriting.

05:23:34

I'm initializing this as a super class as well as activating the main window.

05:23:39

What this translates to is I am activating my super class queue main window.

05:23:46

And I'm giving my super class my class that we just designed.

05:23:51

This is how we set up the inheritance for queue main window.

05:23:55

What do we want to create?

05:23:57

Well, I can set my window title now.

05:24:01

We know that.

05:24:02

What do you want to call it?

05:24:04

Interest.

05:24:05

Interest me.

05:24:06

2.0.

05:24:07

I don't know.

05:24:08

That's kind of cool.

05:24:09

Okay.

05:24:10

Let's give it our resize.

05:24:11

What would the width and height of the app like to be?

05:24:14

Let's say to kick things off 800 and 600 already.

05:24:19

Because I'm inheriting Q main window, I don't have a queue widget yet.

05:24:24

So we can actually make that locally inside our constructor method.

05:24:29

So let's say our main window.

05:24:31

Let's say that's equal to our queue widget.

05:24:33

Like so, I don't need self because it's not going to need that.

05:24:37

It's used and constructed right here.

05:24:40

Let's create all the objects we want to see on the screen.

05:24:44

I'm looking if I run my class.

05:24:47

What objects do we want?

05:24:48

Well, if I run this app, I want three text labels at the top and three queue line edits.

05:24:54

That's going to be in the first row.

05:24:56

I want my tree view to push buttons and then for now a queue label.

05:25:01

Let's start off just in the first row.

05:25:04

So interest rate, initial investment.

05:25:07

Let's say rates text.

05:25:10

I have that.

05:25:11

I'm going to say rates input.

05:25:14

Let's create one for initial text.

05:25:20

We'll create one for initial input.

05:25:25

We can create one for years, so years text.

05:25:29

And we can say years input.

05:25:32

Now that I have those sorted, I can just go through and I know these are going to be queue labels.

05:25:37

So I'll say queue label.

05:25:38

Take that two times.

05:25:40

We have two more.

05:25:42

And then our next one we know is going to be a queue line edit.

05:25:46

So let's get this all prepared for us.

05:25:50

All right.

05:25:51

In the first queue label rate text, we can just say like interest rate.

05:25:58

This is going to be in a percentage looking good.

05:26:04

So our first one is interest rate.

05:26:06

Then we have our initial investment.

05:26:10

Our final one is going to be years to invest.

05:26:15

So our row, I have all those objects.

05:26:19

This is going to now bring me into let's say creation of our tree view.

05:26:26

So how do we use tree view and how do we get items to it?

05:26:30

What I need to do is I'm going to create something like a model.

05:26:34

And this model is ultimately going to hold my tree view.

05:26:38

And it's going to allow me to add items to this model.

05:26:42

Self-domodals and object from this nifty class that we've imported from our QTGY.

05:26:50

I can then create my tree view.

05:26:53

Let's say tree view is equal to Q tree view.

05:26:56

It doesn't take any arguments right now.

05:26:59

I can take my tree view.

05:27:01

So self-thought tree view.

05:27:03

And I would like to set the model to become my model.

05:27:09

Great.

05:27:11

Look at that all come together.

05:27:13

We have our starting row.

05:27:15

I have created my Q tree view.

05:27:18

And I'm preparing it to accept items within the tree view.

05:27:22

And we are setting our model.

05:27:25

Then our last three things are I want a few buttons.

05:27:28

So I'm going to start off by creating my buttons and say let's say I have a count button.

05:27:35

And let's also say I have a clear button.

05:27:39

Our count button can say calculate and our clear button can say clear.

05:27:45

Then I'm going to create a figure.

05:27:49

Now, in the end, ultimately this is going to hold my chart.

05:27:54

But I haven't introduced data visualization yet or our new module that we will use for this.

05:28:01

So for now I'm just going to say Q label.

05:28:04

And I can just say chart will be here soon.

05:28:11

That's just like place over text.

05:28:14

Next up we have all the objects.

05:28:17

What should we be going into?

05:28:19

We should be going into our design.

05:28:22

We can take our design for our app.

05:28:25

So let's create that.

05:28:26

I'm going to create my master layout.

05:28:28

I'm inside in it so I can use self like that.

05:28:31

I know that I want it to be in a column.

05:28:34

I know that I'm going to have row one and that is our QH.

05:28:38

And we also know that we also have row two.

05:28:41

That can be our QH as well.

05:28:44

Now within row two, there will also be two columns.

05:28:49

If I created those now, I can just say column one.

05:28:52

That's my QV.

05:28:54

And column two is also our QV bars.

05:28:58

Let's start off with row one.

05:29:01

So I can take my row one and let's add all of our widgets to them.

05:29:06

So I'm going to actually copy this.

05:29:08

I know I'll be needing it.

05:29:10

The first element we want is going to be our rate text.

05:29:14

Our rate input.

05:29:17

Let me get the other four added.

05:29:20

We have everything added to the first row.

05:29:23

I can carry on now to row two.

05:29:25

Now within row two, I have columns.

05:29:28

So let's begin with those columns actually.

05:29:32

I'm going to take column one.

05:29:34

We want a lot of things in here.

05:29:36

Initially at the top, I want my preview.

05:29:39

So I can add in my preview itself.

05:29:42

Directly under tree view.

05:29:44

We would like our Calculate button.

05:29:47

Bringing us to directly under our Calculate button.

05:29:50

We can just insert that clear button.

05:29:52

Let's take a look at what we want the app to look like as well.

05:29:57

One more time.

05:29:58

I have put everything in the column.

05:30:00

I now just need to add my Q-label to my second column.

05:30:04

Before we can add it into our row.

05:30:07

Taking column two, adding the widget.

05:30:10

What would you do we want to add here?

05:30:11

Well, I want my figure to be here eventually, which will be a chart.

05:30:16

Great.

05:30:17

We have our two columns.

05:30:18

Let's take row two.

05:30:20

And I would like to add layout.

05:30:22

Row one.

05:30:24

And row two.

05:30:27

I can take my master layout.

05:30:29

No.

05:30:30

We can add layout to that.

05:30:32

And at top, we want to say row one.

05:30:35

And row two.

05:30:37

I can see a little mistake here, I threw off.

05:30:40

Right here, I'm adding to my row row one and two.

05:30:44

This should actually be column one in column two.

05:30:49

Set.

05:30:51

We can take our main window.

05:30:53

We can set that layout.

05:30:55

And we can say self dot master layout.

05:30:58

Aw, great.

05:30:59

Everything's set up and it's ready for running.

05:31:03

Let's come outside of our class real quick.

05:31:06

Because we don't have anything.

05:31:08

So if name is equal to main.

05:31:12

Then let's create our app object and say queue application.

05:31:16

We can create an object and say, well, let's say my app is equal to our finance app.

05:31:22

Let's say my app dot show.

05:31:25

And then let's take our app.

05:31:27

And let's execute our app.

05:31:31

Before we run our app, we've set layout.

05:31:34

Now I'm inheriting queue main window.

05:31:37

And we've seen this before with our queue widget.

05:31:40

Because we're inheriting it.

05:31:42

I want to set like a central window.

05:31:46

So I can say set central widget.

05:31:49

What do I want the main widget to be?

05:31:52

Well, my main window.

05:31:54

That's my main widget.

05:31:55

So I'm going to set that here in line 62.

05:31:58

So the last and final part of using our design with the queue main window.

05:32:02

When we run the application, we see everything come to life.

05:32:06

Now this looks almost ready to go and ready for the next stage.

05:32:11

But this preview is huge.

05:32:14

Ideally, I want these to be swapped.

05:32:17

So chart will be here soon.

05:32:19

This should take up the most space.

05:32:22

How can we do that?

05:32:23

We've done this before.

05:32:25

Remember, I need to set the width in the percentage of my columns.

05:32:32

Let me close our application.

05:32:35

Let's find right here.

05:32:38

Let's give this a try.

05:32:39

So I'm going to say column 1 is going to occupy 20%

05:32:44

column 2 is going to occupy 80% of the screen.

05:32:48

Looking much better.

05:32:50

This is how I want the app to look.

05:32:52

We are ready to go.

05:32:54

In the next lesson, we are going to convert your data

05:32:58

and get it into our preview and calculate our interest rate.

05:33:03

Starting to visualize our data before we take the data we've created

05:33:08

and generate a chart or a plot with that.

05:33:12

I'll see you guys in our next lesson.

05:33:24

Thank you.

05:33:48

Great.

05:33:49

We have our app set up in the initial design ready to go.

05:33:53

Now we need to talk about how we are going to calculate our interest

05:33:58

and how we can use what we calculate to put into our

05:34:04

preview and into our chart.

05:34:07

What are the steps we need to do in order to calculate our interest?

05:34:11

Well, if we take a look here, I want to add the interest

05:34:15

calculation to the queue tree view.

05:34:18

So we are going to create a method.

05:34:21

And this method is going to do all of the following.

05:34:25

It's going to convert all our input fields to numbers.

05:34:30

So all of these guys will be converted to numbers.

05:34:34

And we do want to try to catch any errors.

05:34:37

So think about that.

05:34:39

What error could occur in this program if we try to convert these fields to numbers?

05:34:46

What if the user enters something that's not a number?

05:34:50

We want to catch that and alert the user to this.

05:34:54

So think about queue message box.

05:34:57

Once we've converted all of our input fields to numbers,

05:35:01

we want to then create a list for every year.

05:35:08

I want to multiply the total investment by the interest rate.

05:35:13

Our calculation is right here.

05:35:16

I can create a tree view.

05:35:18

And each item in here is going to be something called a queue standard item.

05:35:24

We can import this into our project.

05:35:27

This is going to take a single item that we want to add to a tree view.

05:35:33

We can add our item year and item total to our tree view as a list.

05:35:39

So think about how can we do that as a list?

05:35:42

Finally, once we have data in our box,

05:35:46

I want a save button to appear on my screen.

05:35:51

Initially, when the app starts, we should not have a save button

05:35:55

because you can't save if we don't have any information.

05:36:00

So pause the video, read through each of these steps.

05:36:04

What would you need to do in order to achieve or to solve each of these steps?

05:36:10

Here, I am using two calculate the interest,

05:36:13

the value that we enter into those fields.

05:36:17

So this interest rate, I could store that in a variable and use that.

05:36:22

And then this initial investment, that's like my total.

05:36:25

I could store that in some variables as well.

05:36:28

This calculation is the equivalent to the output of our interest rate.

05:36:34

The input that we entered in number of years,

05:36:37

you can see that that's displayed in the first column versus the second column.

05:36:43

Let's take a look at converting all of our input fields to numbers

05:36:48

and how we could catch any errors with that.

05:36:51

We have our try and accept statements.

05:36:54

What do we want to try to do?

05:36:57

We are creating these local variables in the function.

05:37:00

And we're trying to convert all of our initial properties to a number.

05:37:08

Now remember, a Q line edit.

05:37:11

We can get the text value of a Q line edit by using the text method

05:37:17

and linking it to our Q line edit object.

05:37:21

Now that I have the text value,

05:37:24

I want to try to convert that to a decimal, a float number.

05:37:29

We try to take our values we entered and we convert them as we need them.

05:37:34

I'm going to try and catch any errors.

05:37:37

Specifically, the errors that I want to look out for are value errors.

05:37:42

So if the user enters something that is not a number,

05:37:47

I want to catch that as a value error.

05:37:50

And to alert the user, we can use our nifty Q message box

05:37:54

and just give the user a warning and say,

05:37:57

you need to enter a number, please try again.

05:38:01

We've now converted all of our input fields to numbers

05:38:05

or we've caught the errors to do so.

05:38:08

What comes next?

05:38:10

Well, we need to calculate our interest.

05:38:14

We had a local variable called initial investment.

05:38:18

But I don't want to change that variable that value.

05:38:22

I do want to create that so I can change it.

05:38:26

So I'm making a variable total.

05:38:29

And whatever our initial investment was,

05:38:32

that is now the value to this variable total.

05:38:37

Try and break down what's happening here as I go through.

05:38:41

Where do these correspond to what you see in your app?

05:38:46

For every year in the number of years I entered, which is essentially this,

05:38:55

I'm going to take my initial investment my total.

05:38:59

Every year I want to add the previous total,

05:39:03

and I want to times it by the interest rate.

05:39:07

So every time this runs,

05:39:09

this is going to start with the first initial investment,

05:39:14

multiplied by the interest rate.

05:39:17

But then the second year comes,

05:39:19

and you can actually see here in my preview

05:39:22

that the numbers change it because I'm earning interest

05:39:26

off my initial interest and investment.

05:39:30

So as the years go on, it's actually updating.

05:39:34

That's what's happening here.

05:39:36

I can create an object item here and item total.

05:39:40

And remember to add these two-hour queue preview,

05:39:43

I'm going to use that new class, queue standard item.

05:39:47

So I'm adding a year and I'm adding a total.

05:39:51

I can then append a row.

05:39:55

This method I'm using with queue preview,

05:39:59

specifically to append a row,

05:40:02

which means a row is going to have more than just one item in there.

05:40:06

Remember that we said,

05:40:07

we need to add a list.

05:40:09

My item year is column one.

05:40:12

My item total is column two.

05:40:16

Now this is kind of strange.

05:40:18

What's going on here?

05:40:19

Well, a string format specifier.

05:40:22

This allows us to format all of our floating points with two decimal places.

05:40:27

This specific syntax is telling us the number that

05:40:32

should be formatted or how many digits afterwards.

05:40:35

I want two digits after the number.

05:40:38

And you can see here,

05:40:40

76 cents or 42 cents.

05:40:44

That's what we are formatting.

05:40:47

Where is everything coming from in the app?

05:40:50

Well, let's keep with our color coordination.

05:40:52

Our goal now is to head back into the escode.

05:40:56

I want to be able to program a calculate interest method

05:41:00

that when we call this method,

05:41:02

it's going to insert all of our data

05:41:06

into this queue preview.

05:41:09

As an added bonus,

05:41:10

try to create a reset method.

05:41:13

When I click the reset button,

05:41:16

I want all the contents in my preview.

05:41:20

My interest rate,

05:41:22

investment in years.

05:41:23

I want those to be reset.

05:41:25

How can you do that using the clear method?

05:41:28

I'll see you guys over in our next lesson.

05:41:46

It's now time to calculate our interest rate

05:41:59

and display that in our preview.

05:42:02

Let's go down and let's create a new method

05:42:04

after our constructor.

05:42:06

Right here,

05:42:07

I'm going to make a method.

05:42:08

And I can call this calc interest,

05:42:11

giving itself.

05:42:14

And in the beginning,

05:42:15

I'm going to create a variable called initial investment.

05:42:22

I know that it's going to have a value,

05:42:24

but currently it's none.

05:42:26

We want to try to do a few things.

05:42:29

I want to take all of our inputs

05:42:31

from the top of our app.

05:42:33

So our initial investment,

05:42:35

the interest rate,

05:42:36

and the number of years.

05:42:38

And I want to convert those to numbers.

05:42:41

So we need to check and try to do that.

05:42:44

Let's create a try statement,

05:42:47

and let's say,

05:42:48

okay,

05:42:49

interest rate,

05:42:51

we have that.

05:42:52

I am going to get my initial investment

05:42:55

and then we're going to have the number of years.

05:42:58

For interest rate,

05:43:00

let's convert a float.

05:43:03

And we want to get our input,

05:43:06

something of input text,

05:43:08

rate input.

05:43:10

We created that initially.

05:43:12

That's our queue line edit.

05:43:14

And we can get the text value of a queue line edit

05:43:17

by using the text method.

05:43:20

We can do the same thing for our initial investment.

05:43:24

This is called initial input.

05:43:27

Get the text.

05:43:28

For number of years,

05:43:30

well,

05:43:31

calculate the interest of number of years

05:43:33

is usually done in int,

05:43:35

so whole numbers.

05:43:38

So let's just convert that to an eight.

05:43:40

Get the text.

05:43:41

Awesome.

05:43:42

If this doesn't work,

05:43:44

let's throw an exception.

05:43:46

So a value error.

05:43:48

So you must enter a number.

05:43:50

You can't enter a space,

05:43:52

a letter,

05:43:53

anything like that,

05:43:54

or it's not going to work.

05:43:56

If this occurs,

05:43:58

let's give the user a nice warning.

05:44:02

So I can do that by using our queue message box,

05:44:05

warning.

05:44:07

It's parent is myself.

05:44:09

We can say,

05:44:10

okay,

05:44:11

error,

05:44:12

and let's just say,

05:44:13

invalid input,

05:44:15

and turn a number.

05:44:17

So looks great.

05:44:19

If that's the case,

05:44:20

you can return that.

05:44:22

We now at this point have

05:44:24

three number values

05:44:27

that we want to use to

05:44:29

calculate our interest.

05:44:31

Do you remember the equation we're looking for?

05:44:34

Let's try this calculation.

05:44:36

I'm going to create a new variable

05:44:38

because I don't want to edit

05:44:40

the actual value of my initial investment,

05:44:44

but I am going to use that as a starting point.

05:44:47

What I can say here is I can say,

05:44:49

for every year in the range of one,

05:44:54

because if I have an investment,

05:44:56

the minimum is one year,

05:44:58

and my variable number of years plus one.

05:45:03

So for every year,

05:45:05

if I have my investment for 10 years,

05:45:08

this loop is going to repeat 10 times.

05:45:11

Every time it repeats,

05:45:14

I'm going to take my total,

05:45:16

which the first time this runs,

05:45:18

that is the initial investment.

05:45:20

And I would like to add the total,

05:45:23

but I'm going to multiply that by my interest rate,

05:45:28

divided by 100.

05:45:33

Great, we have this.

05:45:35

I can take my item year.

05:45:38

Now, in my item year,

05:45:40

I would like to add an item to my tree view.

05:45:45

In order to do this at the top,

05:45:48

I imported a class called Q Standard Item.

05:45:52

This allows us to add an item to our tree view,

05:45:57

which if we go up a little bit,

05:45:59

we have right here standard item model.

05:46:02

I'm going to add a standard item to this model.

05:46:07

Going back,

05:46:09

what do we want to add as the item year?

05:46:12

Well, I want to add my current index,

05:46:15

so the year,

05:46:16

that's like, for I,

05:46:18

for every year,

05:46:19

I want to add that current year to my tree view.

05:46:22

Then I want to have the total.

05:46:25

How much did I earn that year, essentially?

05:46:28

Inside here,

05:46:30

we want to put in format our code.

05:46:33

So I can do something a little bit strange here.

05:46:37

Let's give ourselves some curly braces.

05:46:40

And let's go to the end of our total.

05:46:43

And I want to cut off the last two decimals.

05:46:47

So I can say two F.

05:46:50

I can then format my total,

05:46:54

which we initially collected right here.

05:46:57

That's being formatted to only secure two decimal points.

05:47:03

What we want to do is I want to take my model that we created.

05:47:07

Really our models that tree view.

05:47:09

The fancy method append row allows me to append a list.

05:47:15

In this list, in the first column,

05:47:18

I want it to be item year,

05:47:20

and then I want it to be item total.

05:47:23

Just like that.

05:47:24

This pretty much works.

05:47:26

As a bonus, I ask you to actually implement a reset method.

05:47:32

So very quickly, I'm going to do that.

05:47:34

Let's call a method reset and say stuff.

05:47:37

For this, we didn't really have to do too much.

05:47:40

What do you want to reset?

05:47:42

Well, we're going to reset our rate in put.

05:47:45

We're going to reset our initial input.

05:47:49

And then finally, we're going to reset our years in put.

05:47:52

We can just use clear because each of those is a queue line in it.

05:48:00

What is left to do?

05:48:03

Well, let's go up here now.

05:48:06

We just need to go at the bottom of our in it.

05:48:09

And we need to take our buttons.

05:48:11

So I have a count button and we have a clear button.

05:48:15

And we want to say when the clear button is clicked,

05:48:18

we want to connect to our reset method.

05:48:22

When the count button is clicked, we can connect to,

05:48:27

well, you guessed it.

05:48:29

We want to connect to the count interest method.

05:48:33

All right.

05:48:34

Let's run it.

05:48:35

Let's see if we can take our data.

05:48:38

Calculate the interest and display that into our queue.

05:48:42

Let's say we have an interest rate of 8%.

05:48:46

The initial investment can be 10,000.

05:48:49

And years to invest 15 years.

05:48:53

Calculate?

05:48:54

Look at that.

05:48:56

We did that.

05:48:57

I'm going to make this a bit wider.

05:48:59

Okay?

05:49:00

But this preview is working great.

05:49:03

If I click clear, you can see that we've cleared all of our inputs.

05:49:09

Let's just end this on a high note and add the final two touches.

05:49:14

Let's make the preview a little bit wider and also let's clear the preview.

05:49:19

Going up here, let's just change this to a 30% with and a 70% with.

05:49:25

Going down to our reset.

05:49:27

Let's take our model.

05:49:29

Let's say self-dot model.

05:49:31

Clear.

05:49:32

Try it one more time.

05:49:34

Again, 8%.

05:49:35

Let's say 10,000.

05:49:37

Let's say 15 years.

05:49:39

Calculate.

05:49:40

Look at that.

05:49:41

Clear.

05:49:42

Everything is cleared.

05:49:44

We are looking great.

05:49:46

We are about to head over into our next lesson.

05:49:49

And we are going to introduce the new topic of data visualization.

05:49:54

Python.

05:49:55

This can become incredibly useful in your Python journey in your career as a data.

05:50:00

Analyst or a Python developer.

05:50:02

I'll see you in our next lesson for the introduction of Matplotlib.

05:50:08

Music.

05:50:32

It's time to get our hands dirty and jump into how can we take all of our data.

05:50:37

In the tree view and how can we use that to generate or create a chart.

05:50:44

To do this, we are going to use a powerful Python library called Matplotlib.

05:50:50

Let's jump in and explore how this new module works and how we can use this to our advantage.

05:50:57

In order to import Matplotlib, I'm going to do two things.

05:51:01

Number one, I can import Matplotlib.

05:51:04

I'm going to give it a nickname.

05:51:06

I'm going to reference it as PLT.

05:51:09

This is an extremely popular naming convention that you will see in other code that uses this module.

05:51:17

I'm giving it a nickname PLT, which is like plot that I can use at later stages in my code.

05:51:25

Now, Matplotlib and PICUT actually use different backends.

05:51:32

So, we need a way for them to communicate and talk to each other.

05:51:37

Because we are using Matplotlib with PICUT, we are going to import one additional class for our use.

05:51:46

I'm going to import from the backend modules of Matplotlib.

05:51:52

I'm going to import a class called Figure Canvas QT.

05:51:57

This is a really long name, so it's popular to see also renaming that class to figure Canvas.

05:52:05

So, I'm importing this class and I'm renaming that as Figure Canvas.

05:52:11

This acts as a bridge, and it allows us to create charts or Canvas objects.

05:52:19

And that's acts as a container, so it allows us to wrap our chart in a Canvas.

05:52:27

And this allows us then to take this wrapped Canvas and put it into an app like PICUT.

05:52:35

This is why we use this class, Figure Canvas.

05:52:41

Take a look, pause, have a read through.

05:52:44

I'm using the backend of Matplotlib to wrap my chart to use in PICUT.

05:52:53

Let's take a look at some popular methods that we will use for data visualization.

05:52:59

Anytime we're working with the module, Matplotlib.

05:53:04

This is one of our most powerful tools in Python.

05:53:08

When it comes to data visualization, you will most likely see two popular libraries while working with Python.

05:53:15

One being Matplotlib, and for its simplicity, and used in scientific studies.

05:53:21

But two, another popular module that you could use is called Plotlib.

05:53:26

In this course, we are just going to jump in here and use Matplotlib as it's easier to start and easier to understand.

05:53:33

You can hit the ground running with your data visualization.

05:53:37

We can use this to create simple plots, line graphs, scatter graphs, anything like that.

05:53:44

What we are focusing on in this specific project is going to be a line graph for us to see how much interest we're earning.

05:53:53

Screen shot, or write this down, take notes.

05:53:56

Anytime you see a table with me explaining these new methods, it means you're going to be using them more than just once.

05:54:03

It's a good idea to write them down to understand this new library as a whole.

05:54:08

The first method we have is called subplots.

05:54:11

This can generate one or more plots in a single figure.

05:54:16

So, imagine, for example, here is one plot.

05:54:22

What if I want four plots? Well, that's one figure. Now I break it into four plots.

05:54:28

I can use this method to do that.

05:54:31

We have the plot method, and this will try to plot the data that we give this method.

05:54:38

So, this method does take an argument.

05:54:41

It takes the data you want to see, and it's going to try to plot that.

05:54:47

You've seen this method with PICUT. It's also a part of the map plot live.

05:54:51

Once we have this plot, we want to show this plot.

05:54:56

For readability for anyone using your app, it's good to give your app names, and more specifically your chart.

05:55:03

Your x-axis, your y-axis, and the overall title of this chart.

05:55:09

The x-axis, it could be the length of time, years, and your y-axis could be how much money your earning.

05:55:18

The title of your chart could be something like interest rate.

05:55:22

We have a method called figure, and we use this to generate a new figure.

05:55:29

Or if we already have a figure, I can get a reference from that.

05:55:33

But for this app, and to start off, we are specifically focused on creating a new figure.

05:55:38

And finally, we are going to see the draw method, and this is used to redraw a figure and update its contents.

05:55:47

Think about that.

05:55:49

Let's take a look at how we can now set up a plot.

05:55:53

If you remember, when you initially designed your app, you initially designed your app in the chart portion of it as a cue label.

05:56:03

We said in our code, self.figure equals cue label.

05:56:10

Well, now it's time to change that.

05:56:12

We are going to change it from cue label to say plot.

05:56:16

Remember, we imported that plotlib, and we're going to call the figure method, creating a new figure.

05:56:24

Now that I have a figure, I'm going to be working with this figure in PiQT.

05:56:31

So I need to give it to the class that we imported.

05:56:36

This figure canvas class allows us to work with map plotlib and PiQT together.

05:56:43

We are giving it the plot that we created.

05:56:47

Then we are just adding it to our row.

05:56:51

So you can do this entirely on your own.

05:56:53

It's just updating and tweaking a few parts of your design, your initial layout.

05:56:59

Returning to our method.

05:57:02

Now, we have one method for calculating interest in our application.

05:57:07

Our code for generating this plot is going to go within that method.

05:57:13

Now, these steps are not in any order at all.

05:57:16

Can you reorganize them and put them in the order that they should be based on the way our code is running?

05:57:23

If I take them, let's reorganize them.

05:57:25

OK, you can see all the methods that I previously introduced.

05:57:29

I'm using here to generate my plot, my chart.

05:57:33

We are creating a new plot and I'm making a list of years based on the input that was collected from our queue line edit.

05:57:45

I'm using a list.

05:57:47

It's going to range a certain amount of times.

05:57:50

We're obviously going to start with at least one year.

05:57:53

And then we want to go for however many years we entered into our queue line edit.

05:57:59

I'm adding one because Python starts on zero.

05:58:04

Remember that?

05:58:05

We are creating a list of interest over the years and what you see here is called the list comprehension.

05:58:12

This is a slightly more advanced Python topic.

05:58:15

In your Python journey, you may have used list comprehension before or seen them around.

05:58:21

But don't worry, in the next few slides, I will break down the specific example for you.

05:58:27

The final three points we have are we want to try to plot the data and then that data we plot.

05:58:34

It's going to make a chart.

05:58:36

I want to give all the titles to my x-axis, my y-axis, and just the chart in general.

05:58:44

Our chart is 100% set up.

05:58:48

I now want to update my chart so we can see it on the screen.

05:58:53

Another thing you see here is a x.

05:58:56

You could call this anything, but you will see as a popular name and convention, the variable a-axis used when working with not plot lip.

05:59:05

What is list comprehension now?

05:59:08

When I break that down, what are we trying to achieve in this list example?

05:59:14

Well, let's break it down.

05:59:17

What I want to do is I have a list and this list is called totals.

05:59:24

And I want to add a certain number of elements to this list.

05:59:29

If I'm going to invest money for 10 years, I want there to be 10 different elements in my list.

05:59:39

So in my example, I have said I'm going to invest for 15 years.

05:59:45

So I'm going to repeat something 15 times.

05:59:48

Every single time I repeat this loop, I'm taking my list and I'm appending something to it.

05:59:57

I'm taking my initial investment and I'm multiplying it by the interest rate and the current year.

06:00:03

This is like how much money you would earn after a year.

06:00:08

For example, if I change these numbers and I said 10,000, 10% interest rate, I would be appending the number 11,000 to my list, the first time that ran.

06:00:25

The next time this ran, what do you think we would be having?

06:00:30

Well, it's not going to be 11,000 anymore.

06:00:33

Can we use our input values instead of hard coding these numbers?

06:00:38

We can remember that we collected the value of everything we entered into the inputs.

06:00:45

And we converted those two numbers.

06:00:50

So we already have those as variables.

06:00:52

Let's now use them.

06:00:54

Initial investment interest rate.

06:00:57

That's what we did.

06:00:59

When from this, we changed it down to this.

06:01:02

Now I'm not hard coding anymore.

06:01:04

I'm using the value of my variables, which could be changing.

06:01:08

It's whatever the user enters into the app.

06:01:11

Let's take this one step further.

06:01:14

We now have this.

06:01:16

How can I combine these three lines of code into one?

06:01:20

This is list comprehension.

06:01:23

Now that you understand what we're trying to achieve in this list,

06:01:27

let's combine them.

06:01:29

In our code, you can see that I'm defining a new list called totals.

06:01:35

You can see my square brackets.

06:01:38

Then the calculation for each element in the list.

06:01:43

And this just takes our initial investment in the interest rate.

06:01:47

And it's squaring it based on the year.

06:01:50

So all in all, this is just one number.

06:01:54

This is like 11,000 from my previous example.

06:01:58

Then the comprehension is I'm putting a for loop in my list.

06:02:03

And I want to repeat the number of years that we entered in our input.

06:02:10

Remember we stored that in a list years that we created previously.

06:02:16

Let me return now to what we initially saw.

06:02:20

This was the setup for our code.

06:02:23

Can you implement this?

06:02:25

Let's try it.

06:02:26

I want to start to see some charts on our screen.

06:02:28

Let's head over to VS code.

06:02:30

And I will see you guys in the next lesson.

06:02:32

It's time to implement that plot lib.

06:02:50

You now have a basic introduction to how we can take data and create visualizations using this data.

06:03:08

We have that library called map plot lib or map plot library.

06:03:13

Let's get that into our code.

06:03:16

At the top, we need to get the standard pi plot library or module from map plot lib.

06:03:23

Let's import map plot lib, but the plot plot as PLT.

06:03:30

That's the popular naming convention.

06:03:33

Then remember that map plot lib in pi qt have two different backends.

06:03:39

So there's a special import we can use when working with map plot lib in.

06:03:45

We can say here from map plot lib.bacends.bacendqt5agg.

06:03:57

What I want to say here is I want to import specifically figure canvas qt.

06:04:04

And I can nickname that now as figure canvas.

06:04:09

So PLT and figure canvas are already popular naming conventions.

06:04:15

You may see another code when working with map plot lib with pi qt.

06:04:20

Okay, I'm going to mark those.

06:04:22

We now have this new module imported for our data visualization.

06:04:27

I want to go down.

06:04:29

Remember that our app has this q label.

06:04:34

So I have a property called self dot figure, but initially I set this to a q label.

06:04:40

We now want to redo that.

06:04:42

The value of q label is going to be a figure of some sort.

06:04:49

Now this figure I need to create and convert to a canvas.

06:04:55

Remember that a canvas is like a giant container that's going to hold my figure in pi qt.

06:05:02

So this canvas is going to be an object actually.

06:05:07

And we're going to use that class we imported.

06:05:10

This is like a wrapper.

06:05:12

And it's going to wrap my figure in my canvas.

06:05:16

We can then just go down and we have actually added in here already.

06:05:21

I have taken my column.

06:05:23

I've added my figure.

06:05:25

Let's just change where it says figure.

06:05:27

Let's now add our canvas.

06:05:31

Marking that off.

06:05:32

We've created this new Matplotlib figure.

06:05:36

Racked it in a canvas for pi qt.

06:05:39

And then set the canvas to our column 2.

06:05:44

Okay.

06:05:45

The design part is done.

06:05:47

We now need to take that data and convert that and display this in our chart.

06:05:54

Going down here.

06:05:55

We're going to do this inside our count interest method.

06:06:00

The first part of what we did here was we got our data.

06:06:05

We converted it and calculated the interest to display inside our qt.

06:06:11

What I want to do here is I want to update my chart with our data.

06:06:18

This can be done.

06:06:19

So the first thing I want to do is I want to take my figure.

06:06:24

And I want to clear it off from any old data.

06:06:28

We don't want that.

06:06:29

Then by popular name, I'm going to say ax.

06:06:31

This is like our axis.

06:06:33

I'm going to create a plot.

06:06:35

And I'm going to say figure dot sub plus method.

06:06:41

This will allow us to generate a chart.

06:06:45

And if we wanted to, I could create one figure or I could have four figures within one.

06:06:54

So I've generated a chart.

06:06:56

That's now called ax for all intents and purposes.

06:07:01

Let's create a list of years.

06:07:04

So this is potentially going to be the x axis on my chart.

06:07:10

Because as the years go on, my interest goes up.

06:07:15

So my years is going to be a list.

06:07:18

How many elements do I want in this new list?

06:07:22

Well, remember, if I enter that I will invest for 10 years,

06:07:27

I should have 10 elements in this list.

06:07:31

One through 10.

06:07:33

So within this list, let's say it's going to have a range of one.

06:07:38

All the way to the number of years plus one.

06:07:41

Just like we did up here for our for loop.

06:07:44

We have our years.

06:07:46

I now want to calculate my initial investment.

06:07:50

For this, we are going to do some list comprehension.

06:07:54

Now remember, I talked about this in the slides in the lesson.

06:07:58

This kind of gave you an intro to what list comprehension is.

06:08:02

And how we can nest in a list to repeat a very similar task.

06:08:07

So I have a list of totals.

06:08:11

I'm going to start with calculating the first element.

06:08:15

So the first element, I want to take my initial investment.

06:08:20

And we're going to multiply it by our interest rate.

06:08:24

So that's going to be 1 plus our interest rate divided by 100.

06:08:28

What we want to do is I want to take this and raise it by the year.

06:08:33

That's just one element.

06:08:35

All this is working together as one.

06:08:39

Now I want to repeat this for a number of times.

06:08:43

So I can say you're four years in years.

06:08:49

Remember that years is a list we just created.

06:08:53

So it's going to loop for however many years we have in this list.

06:08:58

Every time it's calculating the interest for the current year

06:09:04

and adding it to this list called totals.

06:09:08

That saves us a lot of code.

06:09:10

And this is more advanced Python that we will see as we progress through our journey.

06:09:16

Next up, I have my data that I want to plot.

06:09:20

So I'm going to take my figure and I'm going to try to plot.

06:09:24

What do I want to plot?

06:09:26

Well, I want to plot the years and I want to plot the totals.

06:09:32

Now that we've given some space there, let's take it and let's give a title.

06:09:38

So I can use the set title method.

06:09:40

I can use the set x label method.

06:09:46

And we can use the set y label method.

06:09:50

Let's give a name to everything.

06:09:52

I've now given the names to the chart.

06:09:54

The last thing I'm going to do here is I am going to take my canvas

06:09:58

and I want to draw on that canvas using that method.

06:10:02

Let's also go down here and I'm going to add in two more clears.

06:10:08

So when we click the reset button, I want my figure to also clear.

06:10:14

I would like the wrapper my canvas to also clear.

06:10:20

Our app is pretty much ready to run.

06:10:22

Let's go through.

06:10:24

We cleared any old charts.

06:10:26

We created a sub plot.

06:10:30

Then we generated data.

06:10:32

So my years is a list.

06:10:34

My totals is all my interest calculated.

06:10:36

Then we set that data to our plot.

06:10:40

Giving it a title and x label a y.

06:10:42

Oh, our y label.

06:10:46

And then we drew on our canvas.

06:10:48

We can run the app.

06:10:50

Let's say an interest rate of 10%

06:10:52

with a $15,000 investment over 20 years.

06:10:56

Calculate.

06:10:58

Look at that.

06:11:00

We took our data.

06:11:02

It's not only displayed in tree view.

06:11:04

It's also displayed in an image.

06:11:06

A picture.

06:11:08

This looks incredible.

06:11:10

Our app is almost ready to go.

06:11:12

I want to have the ability to save this data as a CSV file.

06:11:16

And this chart as a picture.

06:11:18

Let's head into the next lesson.

06:11:20

And let's talk about how we can save all the data we've just generated.

06:11:24

I'll see you guys there.

06:11:46

We've come so far.

06:11:54

We have implemented not only a new tree view, which is like a table,

06:11:58

but we've also implemented a chart using that plot live.

06:12:02

Our app has come to life.

06:12:04

It's now time to add the saving functionality.

06:12:08

I want us to be able to save all of our table data as well as our chart.

06:12:14

Let's take a look at how we can achieve this.

06:12:18

Does this look familiar?

06:12:20

Well, it should.

06:12:21

This is our method from our image app that we built.

06:12:25

In that image app, we made a save method.

06:12:29

And the job of this method was when it was called.

06:12:32

It was going to save our newly edited photo

06:12:36

within a new folder.

06:12:38

So remember, we use the OS module to achieve this.

06:12:44

OS is our operating system.

06:12:47

We used our path to join, or more specifically,

06:12:51

to link our directories together.

06:12:54

We're going to use that now again.

06:12:56

We can also use the function Make Derr,

06:12:59

which allows us to make a new directory,

06:13:02

or specifically make a new folder.

06:13:06

So start to think, how could you create this?

06:13:11

How could you create a save method for this new app

06:13:15

we're making using the OS module?

06:13:19

Let's take a look at how we can do this.

06:13:21

Here's my code written now.

06:13:23

So in this method, I want to be able to create a save folder

06:13:27

and it's going to save my queue-tree view data as a CSV file.

06:13:33

Okay?

06:13:34

Then it's going to take our chart.

06:13:37

And it's going to save the chart as a PNG or as a picture.

06:13:42

So I need to do a few things here.

06:13:45

We need to get our existing directory.

06:13:49

Remember, we have used this before.

06:13:52

We use this in our image app, our queue-file dialogue,

06:13:56

and our get existing directory.

06:13:59

If we have our path,

06:14:02

then I want to make a new folder called saved.

06:14:07

In this folder, this is where all of our charts

06:14:12

and our CSV files will be saved within our app.

06:14:16

Then what we could do is I can create a new file path

06:14:21

and it just links just like the image app.

06:14:25

Remember, we created a new edited folder.

06:14:30

And we took this new folder, and we linked it

06:14:33

onto the end of our directory.

06:14:36

The same thing is happening here.

06:14:38

I create a new saved folder,

06:14:42

and I link that to the end of my directory.

06:14:46

Now that I have this new directory,

06:14:48

I'm taking this new directory.

06:14:50

And I am adding my CSV file that I've just created

06:14:57

using my data to it.

06:14:59

Now that we have that, we can open this new file

06:15:04

and I want to write inside of this.

06:15:08

The name in my CSV file is going to be year and total.

06:15:13

It's like two columns.

06:15:15

Then, for every row in my preview,

06:15:21

remember, our preview is called self dot model.

06:15:25

Let me repeat that.

06:15:27

For every row in my preview,

06:15:31

I am going to get two things,

06:15:35

a year and a total.

06:15:38

And I'm taking this from the index,

06:15:41

the position of the first column zero in my preview.

06:15:47

The second column is that position one.

06:15:50

That contains my total.

06:15:52

I can use the data method to do that.

06:15:55

Once we have this new data for my row,

06:15:59

then I want to write in my CSV file.

06:16:03

I'm going to write two things with a comma in between.

06:16:07

They are going to be formatted to year.

06:16:11

Year will be in the first one.

06:16:14

Total will be in the second one.

06:16:17

That is what we see happening here.

06:16:20

Pause the video.

06:16:22

Read through, break it down in our own words.

06:16:25

We're going through every row in our queue tree view.

06:16:30

And what we're trying to do is we are going to get the data from the row

06:16:34

and save that into our CSV file.

06:16:38

The code you see here,

06:16:40

this only applies to our CSV.

06:16:43

In order to save our chart,

06:16:45

it's actually much easier.

06:16:47

Thankfully, Matplotlib has a method for us called Save Fig.

06:16:52

This method works just like the Save method we've used previously in our apps.

06:16:59

I can use Save Fig and I'm going to give it the folder name.

06:17:05

So previously the folder was saved here.

06:17:09

You could call it results.

06:17:11

And I'm giving the name to this picture.

06:17:14

As a friendly reminder at the end,

06:17:17

what you could do is you could include a queue message box or a pop-up.

06:17:21

And just tell the user or give them some reassurance that,

06:17:25

hey, yes, your data has been saved.

06:17:28

You can use your queue message box with the information method

06:17:33

and the warning method.

06:17:34

And we can link a few things and say, hey, congratulations.

06:17:38

Your Save was successful.

06:17:40

Or, no, you actually didn't select where you want to save, too.

06:17:45

Let's jump back into VS code.

06:17:47

And let's begin to wrap things up.

06:17:50

The first thing we need to do to wrap up

06:17:52

is to add our Save functionality.

06:17:55

I'll see you guys in our next lesson.

06:18:10

It's time to add our saving functionality.

06:18:25

Remember, when we added the Save method within our image editing app,

06:18:30

we needed something called QFile dialog.

06:18:34

I'm going to import that right now.

06:18:37

We can next go down to the bottom of our class.

06:18:41

After our calc interest, I'm going to go right here before reset.

06:18:46

I'm going to create a method called Save Data.

06:18:51

Give me that self.

06:18:53

Inside here, I want to create a path or my directory path.

06:18:58

So let's say directory path is equal to our QFile dialog.

06:19:04

We've got get existing directory.

06:19:07

We've used this before.

06:19:09

You've seen it.

06:19:10

It's going to allow us to choose that directory that we want.

06:19:13

Inside here, we want to give it self.

06:19:17

And I'm going to give it a caption, so like select directory.

06:19:23

Let's make sure I spelled self correctly.

06:19:26

I'm going to check if this is true.

06:19:29

So if I did indeed capture a directory,

06:19:32

we need to make sure that we selected something.

06:19:34

If we did, I want to create a new folder.

06:19:38

So like a folder path.

06:19:40

Now to do this, remember, I need OS.

06:19:43

We don't have OS yet.

06:19:45

Go up and let's import OS.

06:19:47

Right down here, I'm just going to say import OS.

06:19:52

All right, back down.

06:19:55

OS path, I want to join together.

06:19:58

What do I want to join?

06:20:00

Well, I want to join the directory path that I've just made.

06:20:04

And then I want to join like a new folder.

06:20:07

So let's call it like a saved.

06:20:10

All right, this is our saved folder.

06:20:12

It's going to contain a CSV file,

06:20:14

as well as an image of our chart.

06:20:17

I'm then going to access my OS.

06:20:20

And let's say OS make dirt.

06:20:23

Inside here, we can say our folder path.

06:20:27

That's the path to make.

06:20:29

We're good. We're ready to go.

06:20:31

Now that I have this new folder called saved,

06:20:34

what I can try to do now is I want to save this CSV file

06:20:39

and join that to my new path.

06:20:42

So let's create a file path and say OS path.

06:20:46

I would like to join together.

06:20:48

What do I want to join together?

06:20:49

Well, I now have this new path called folder path.

06:20:53

And it's going to add results,

06:20:57

which is going to be a CSV file.

06:21:00

We can now open this new file path I've just created,

06:21:04

which technically is a CV file.

06:21:06

We can give it the nickname file.

06:21:09

Anytime that we use this word file,

06:21:12

now it's like a nickname.

06:21:14

And it refers to this file.

06:21:17

This file is our working directory.

06:21:22

With our saved folder with our new CSV file.

06:21:27

So I want to open this CSV file,

06:21:31

giving it the nickname file.

06:21:34

Inside the headers of this CSV file,

06:21:38

I'm going to write some stuff inside.

06:21:40

I'm going to write year and I'm going to write total

06:21:44

before putting all the new information on a new line.

06:21:50

Then for every row in the range of my preview.

06:21:56

So I want this loop to repeat for however many items we have

06:22:02

in our model, which is our preview.

06:22:05

To do this, I can just take our model and I'm going to say,

06:22:08

okay, whatever that row count is of the model,

06:22:13

that's how many times this loop is going to repeat.

06:22:17

Every time this loop repeats, I'm getting a year,

06:22:20

and I'm getting a total that I'm going to add

06:22:24

into the CSV file.

06:22:27

My year, how can I capture the year?

06:22:30

Well, let's take our model.

06:22:32

Let's index, let's get the position of the model.

06:22:35

The row is going to be whatever the current row we're on.

06:22:40

That's just the index of our four loop.

06:22:44

What column is the year going to be in?

06:22:46

Well, the columns in year one, which is at position zero.

06:22:51

Next up, let's just get the data from that.

06:22:55

The total is going to be the same thing.

06:22:58

I can take my model.

06:22:59

I can index the current row, the column is one.

06:23:02

Let's get that data.

06:23:04

Looks great.

06:23:06

Inside our file, I can take my file.

06:23:09

Let's write these new contents in our file.

06:23:12

Every row, it's capturing the year in the total,

06:23:16

and it's going to write in the CSV line after line after line.

06:23:21

What do we want to write in every row?

06:23:24

Well, let's just say I'm going to have data here.

06:23:27

It's going to have a comma, and then I'm going to have more data here.

06:23:31

I can then format that data, how I want it to look.

06:23:36

I want it to look like year and then total.

06:23:40

So let's format it like that.

06:23:42

Great.

06:23:43

We've saved the data from tree view as a CSV file.

06:23:48

What we can do now is I can take my map plot live library,

06:23:53

and I'm going to say save fig.

06:23:56

I want to save my chart as a picture,

06:23:59

and I want to save it in my saved folder, right?

06:24:05

Finally, at the end here, let's just give a nice little message to the user

06:24:09

and say hey, either it's saved or it didn't save,

06:24:14

so just be like save results maybe.

06:24:18

That sounds nice.

06:24:20

What would you like to tell the user like results were saved to your folder?

06:24:31

Then else, I'm making this a part of the initial condition.

06:24:35

So else I was not able to find a path to use.

06:24:41

Then I'm going to give the user a warning.

06:24:44

And I need to alert them to this problem and say save results.

06:24:49

I can put no directory selected.

06:24:54

This looks great.

06:24:55

I'm actually done right here.

06:24:57

But there's one thing we're missing.

06:25:00

I have a save data method.

06:25:02

I should have a save button.

06:25:05

Going up, we don't have a save button.

06:25:08

So I'm going to jump in here to make one.

06:25:11

I'm going to call this save button.

06:25:13

Let's say save button is, once again, a Q push button.

06:25:17

Going down, let's just add it right here in column.

06:25:20

Let's say column one, add widget.

06:25:23

Let's say save button.

06:25:27

Then down with our events, we can take our save button.

06:25:33

Let's give our app a final test.

06:25:37

All right, let's enter a 12% let's say 25,000.

06:25:41

Let's say 20 years calculate.

06:25:44

Let's click save.

06:25:45

This is good.

06:25:46

It asks us where we want to save.

06:25:48

I'll say open.

06:25:49

I'm given an error.

06:25:50

Let's take a look at how we saved this.

06:25:55

Okay, let's do a few things here.

06:25:58

So I'm going to trap this.

06:25:59

The first thing I'm missing is I'm actually, I need a command.

06:26:02

Am I reading this file, a pending, or writing?

06:26:06

Well, I'm writing in this file.

06:26:09

The next thing, let's change this from maker.

06:26:13

Let's say make doors instead, make directories.

06:26:17

And if the directory already exists, is that okay?

06:26:22

Let's just say, yeah, that's okay.

06:26:25

I can save multiple things to that file.

06:26:29

Running my code again.

06:26:31

Let's say 12%, 20,000, 20 years calculate.

06:26:38

Save, where do we want to save it?

06:26:41

Here's fine.

06:26:42

Open results.

06:26:44

We saved to your folder.

06:26:46

Okay, I got that.

06:26:48

Let me move my app or shrink it.

06:26:52

Let's take a look now.

06:26:54

If you check your side folder, you're going to see results.

06:26:58

Here's my CSV.

06:27:00

Okay?

06:27:01

And then you're going to see the chart we saved as well.

06:27:04

It's working our save functionality.

06:27:07

If I return to our app, make it bigger.

06:27:10

We can press clear.

06:27:13

And we need to address our clear.

06:27:16

Let's just change clear to say draw because I want to draw a blank canvas.

06:27:20

And that'll fix our issue.

06:27:24

Okay, this looks great, guys.

06:27:27

I am so incredibly proud of how far you've come.

06:27:32

Let's jump in now.

06:27:33

We're going to add some final advanced design because you've earned it.

06:27:37

I'll see you guys in the next lesson where we're going to talk about how we can add some

06:27:41

styling to our application.

06:27:43

I'll see you in the next video.

06:27:45

You can see that every app you've built.

06:28:13

You've added a little more styling every app.

06:28:18

We started with our warmup that random word app.

06:28:22

And the styling you learned was the layout and the design.

06:28:26

You've gone to the calculator app.

06:28:28

We introduced Q font and how you can import a font to our apps.

06:28:34

In the expense app, we then introduced CSS.

06:28:39

And how you can use CSS and style your apps and buy Qt.

06:28:44

Now, for our final app, let's add in some more styling.

06:28:48

But this is going to be slightly more advanced.

06:28:51

Now that we have a working app, you can query about that dark mode.

06:28:55

This is not something that you should worry about until you have a working product.

06:28:59

But it is a fun feature to add.

06:29:02

And it's actually easier to implement than you may think.

06:29:06

In our interest rate calculator, how can we add a dark mode?

06:29:11

Let's jump in and find out how.

06:29:13

The last thing we want to wrap up with our app is we're going to do a bonus dark mode.

06:29:19

We're going to tweak any fonts we have at any colors and any styling.

06:29:23

When we first launch our app, this is the template we see.

06:29:27

But then if we select our dark mode box, it's going to apply that filter to our app.

06:29:35

You will also see that my chart has actually changed.

06:29:39

I'm going to show you how you can do that as well using map.lip.

06:29:44

In order to get our dark mode implemented, we will use our CSS styling.

06:29:49

Do you remember how do we use CSS and buy Qt?

06:29:54

Well, you should remember our method set style sheet.

06:29:59

And we're going to use that here as well.

06:30:01

I'm going to create a method.

06:30:03

And in this method, I'm going to check if my check box is checked.

06:30:10

Is checked is a method that checks the state of our Q combo box.

06:30:16

So it checks if you have clicked that.

06:30:19

Now this doesn't only work for Q combo box.

06:30:23

If you use a widget called Q radio button for radio buttons,

06:30:29

you can also use this method to check the state of that.

06:30:34

We have the method set style sheet, which is going to allow us for our style sheet.

06:30:41

When our dark mode is checked, I want my background to be a dark color of the whole app.

06:30:50

My Q labels, Q line edit, Q push button, they're going to take a lighter color.

06:30:58

Then my Qt review is also going to be a lighter color text with a darker background.

06:31:07

Let's go back.

06:31:09

What does the app look like?

06:31:11

This is what it's going to look like.

06:31:12

You can see that my font is now light.

06:31:15

My input boxes and my buttons,

06:31:20

Treview is like this lightest dark gray.

06:31:23

The main app component is a very dark gray.

06:31:27

That's what we're actually applying here with our styling.

06:31:33

So remember, in CSS, we want to target an element.

06:31:39

So for example, H1, we want to affect anything with H1.

06:31:44

And it's going to take on the color of the text of white, the font size, the font family.

06:31:50

Well, it works the same in Python Qt, just remember that everything is a string.

06:31:55

I want to affect my entire app, so finance app, background color.

06:32:00

I only want to affect Treview.

06:32:03

Alright, so I target Treview here.

06:32:06

Now that I created that dark mode, I created that apply styles method.

06:32:12

This method, I am linking to an additional method, specifically for toggling or turning on our dark mode.

06:32:21

We have our object that we made that's a Q check box.

06:32:26

Now I want to use a new event.

06:32:29

This event is called state changed.

06:32:32

In this event, triggers when we change the state of an object.

06:32:37

Or to translate that and break it down, this changes when we click a Q combo box.

06:32:44

I'm changing the state.

06:32:46

I'm clicking it.

06:32:47

I'm marking it.

06:32:48

That is what we want to connect to.

06:32:50

I want to connect to my toggle, dark mode method.

06:32:54

In return, I'm actually checking if my Q combo box is checked.

06:33:00

If it is, it's going to apply that style.

06:33:03

Let's wrap things up and let's head back over into VS code and wrap up our final application.

06:33:10

I'll see you in that video.

06:33:34

We are now ready to implement some dark mode and add additional styling to make our app even more unique.

06:33:43

First thing, I'm going to go up top and I want to import Q checkbox.

06:33:48

This is what we're going to be using for our dark mode.

06:33:52

And then going down, let's just create one of an objects here.

06:33:56

Let's say let's call this object dark mode and let's say that is our Q checkbox.

06:34:03

This Q checkbox is going to say dark mode.

06:34:08

Now that I have that, we can add that into our layout.

06:34:12

So right here, I'm going to say self dot row one.

06:34:15

Let's add in that new object we've made.

06:34:18

At the bottom of init, we have all of our events.

06:34:23

Let's take that dark mode.

06:34:25

And let's say when the state is changed, I want to connect to something.

06:34:32

Now we need to make this something.

06:34:35

So I'm going to mark that right now.

06:34:37

After init, let's create a bunch of space here.

06:34:41

I'm going to create a new method.

06:34:44

And I'm going to call this, let's call this applies styles, giving itself.

06:34:49

So first things first, let's set our style sheet.

06:34:53

Remember, this is how we do our styling in PICUT.

06:34:58

So I'm going to create this property.

06:35:01

I'm calling this method set style sheet.

06:35:04

And I'm going to give my app some qualities, some background colors.

06:35:08

Let me add those in.

06:35:10

So I've created the initial styles for my app.

06:35:13

When my app boots up, it's going to have these styles with the initial styles.

06:35:18

I can check if my dark mode.

06:35:21

So I can say if self-dark mode is checked.

06:35:28

We're using this new method.

06:35:30

It's going to check the state to see if it's clicked.

06:35:33

So if it is, I want to do something.

06:35:36

And I'm going to change these values.

06:35:39

So I can take this.

06:35:41

Let's put it inside.

06:35:42

And let me tweak these values.

06:35:44

So you can see now that when my dark mode is checked, my background color is changing.

06:35:50

It was white.

06:35:51

Now it's this dark color.

06:35:53

My backgrounds for my other buttons, my labels, their changing as well as my preview.

06:35:59

All of these are taking effect when my dark mode is checked.

06:36:04

Great.

06:36:05

Let's apply these initial styles.

06:36:08

Remember, when the app starts, it's going to have these styles.

06:36:12

So I need to automatically apply these.

06:36:16

Up inside in it.

06:36:18

Let's just go down here in it and let's say self.

06:36:22

Gotta apply styles and call that method.

06:36:26

Great.

06:36:27

Now, carrying on.

06:36:29

We are going to create a final method.

06:36:32

And I'm going to call this toggle mode.

06:36:35

When this method is called, the only thing that it's doing is it's going to apply

06:36:40

styles.

06:36:41

It's going to call the method we made above here.

06:36:45

What happens is it's going to hit this condition.

06:36:48

If it's checked, it's going to change the styling.

06:36:52

Up in our events.

06:36:54

Right here.

06:36:55

I can now connect.

06:36:56

What do I want to connect to?

06:36:58

Well, I want to connect to this new method that I just made.

06:37:02

So let's say self.togal mode.

06:37:09

Looking nice.

06:37:11

I think my app is ready for a quick run.

06:37:14

Let's test it.

06:37:16

Okay.

06:37:17

Here's our app.

06:37:18

You can see that the styling of everything looks a little different.

06:37:21

I'm going to click dark mode.

06:37:23

Okay.

06:37:24

It is working.

06:37:25

This looks great.

06:37:26

I can turn that on.

06:37:27

Turn that off.

06:37:28

Turn that off.

06:37:29

Okay.

06:37:30

Let's style a few more things.

06:37:31

I'm going to close the app.

06:37:33

I'm going to return to my Calc-interest method.

06:37:37

Right in here.

06:37:39

Let's go here.

06:37:40

I'm going to tweak a few things.

06:37:41

I'm going to say, okay.

06:37:43

Let's make sure that every model is cleared before we calculate a new one.

06:37:50

And let's take our model and let's use this.

06:37:55

We have used this before.

06:37:58

We've said set horizontal header labels.

06:38:02

Inside here, I want my chart to say year.

06:38:05

I want my chart to say total.

06:38:08

Okay.

06:38:09

Then the last little tweak I'm going to do is I want my chart to actually have a style.

06:38:14

So I can take my map plot lib module.

06:38:17

And I'm going to say PLT because that's referencing it.

06:38:21

I want to access style and I want to use.

06:38:25

Now you can look up a few of the other styles they have.

06:38:28

Because this has changed and it will continue to change.

06:38:32

But the style I'm going to use in one of the more popular ones is called C-borne.

06:38:36

So I'm going to add that in right there.

06:38:38

Let's run our app and do a final quick run through.

06:38:43

Let's say 8% interest with 50,000 for 15 years.

06:38:50

I'm going to click Calculate.

06:38:52

It's working.

06:38:53

I'm going to click Clear.

06:38:55

Okay.

06:38:56

We have everything working.

06:38:58

Let's say 8%.

06:38:59

Let's say 5,000.

06:39:01

Let's say 15 years.

06:39:03

Dark mode.

06:39:04

Working.

06:39:05

Calculate.

06:39:06

You can see my chart.

06:39:08

That was working the first time as well.

06:39:10

Looks great.

06:39:11

I have my total label.

06:39:12

My year.

06:39:13

All right.

06:39:14

Let's click Save.

06:39:15

Where do we want to save it?

06:39:17

Open.

06:39:18

We're working.

06:39:19

This is incredible.

06:39:20

This is absolutely amazing.

06:39:23

We have shot for exactly what we want in our application.

06:39:27

You should feel so proud of yourself.

06:39:30

You have been introduced so much in this course.

06:39:34

Many new advanced topics that don't just include PICUT.

06:39:38

I will see you guys in our next video.

06:39:43

Congratulations.

06:39:44

And spend some time reviewing your code and seeing how everything came together.

06:39:49

I'll see you in our next video.

06:39:52

Thank you.

06:40:17

Congratulations.

06:40:19

You have just completed the building apps in Python with PICUT course.

06:40:25

I am so proud of how far you've come.

06:40:28

Throughout these last modules, you have been introduced to a powerful framework that's used to create apps in Python.

06:40:37

This framework is a bridge between C++ and Python.

06:40:42

And it's a class-based framework.

06:40:45

Which means you've used everything you've previously learned in the fundamentals of Python.

06:40:51

And you've brought in that knowledge here to create class-based applications.

06:40:56

You now have four fledged capstone projects.

06:41:00

You are introduced to PICUT with our calculator app.

06:41:05

This taught you the layout and the design structure for building apps.

06:41:10

We led into our image editor app or photoqt.

06:41:15

Here is where you learn that you can use multiple modules to create a single application.

06:41:22

You then were introduced to SQL in databases through our expense tracking app.

06:41:28

And for our final project, we brought everything together with our interest rate calculator and data visualization,

06:41:37

which is a powerful tool in Python.

06:41:40

I hope that you've had as much fun as I've had in this course.

06:41:44

And I look forward to seeing you and other courses that I may have in the zero-to-knowing program.

06:41:49

Congratulations and well done.

06:41:52

Before jumping on to any other courses, please spend the next week to hone in the skills you've learned

06:42:00

and try creating your own project using everything that was taught in this course

06:42:06

from data visualization to implementing CSS or adding a database into our applications.

06:42:14

I'll see you guys around.

06:42:16

Nicely done.

00:00

Introduction to Desktop Applications

02:20

Course Overview and Projects

07:20

Setting Up for PiQT Development

10:30

What is PiQT Framework?

13:10

Benefits of Using PiQT

15:51

Understanding Windowed Applications

16:29

Breaking Down System Preferences

16:46

App Widgets Explained

18:50

Designing an App Layout

19:37

PiQT Framework Modules

32:40

Understanding Camel Casing

33:06

Designing the App Layout

33:51

Setting Up Main Window

34:14

Importing QT Modules

35:18

Configuring App Settings

49:10

Handling Events in PiQT

50:44

Creating App Objects

52:30

Designing App Layouts with Rows

53:24

Adding Widgets to Layouts

57:24

Implementing Random Words

01:05:51

Implementing Button Logic in UI

01:06:40

Creating the Q Line Edit Tool

01:07:40

Integrating Loops for Button Generation

01:11:33

Finalizing the Calculator Design

01:13:44

Running the Initial Template

01:22:32

Adding Functionality to the Calculator App

01:23:10

Evaluating Expressions in Python

01:23:55

Implementing Button Click Logic

01:26:11

Using the Eval Function

01:28:45

Error Handling in Calculations

01:39:24

Refactoring to Class-Based Structure

01:42:50

Class Initialization Concepts

01:43:35

Understanding Class Methods and Properties

01:53:30

Creating an Interactive Photo Editing App

01:54:35

Overview of Photo Editing App Functionality

01:55:52

Understanding Q Label Usage

01:56:31

Designing the App with Layouts

01:58:32

Creating the Main Window

01:58:47

Setting Up the Initial Design

02:09:14

Exploring the PIL Module

02:12:30

Using the Pillow Library for Image Editing

02:13:20

Applying Filters to Images

02:15:12

Saving Edited Images

02:15:24

Opening and Editing Images in Python

02:19:10

Exploring Image Enhancement Techniques

02:29:18

Creating the Filter Function

02:29:50

Understanding File Extensions

02:31:22

Getting Current Working Directory

02:33:48

Saving Images with Unique Paths

02:35:21

Loading and Displaying Images

02:45:51

Getting Current Working Directory

02:46:40

Setting Up File Extensions

02:47:28

Listing Files in Current Directory

02:48:32

Loading Files into Q List Widget

02:51:08

Creating the Editor Class

03:02:33

Displaying Selected Images

03:04:35

Connecting Display Functionality

03:06:04

Implementing Image Editing Features

03:06:40

Building Image Editing Methods

03:12:53

Using Lambda Functions for Filters

03:19:16

Implementing Filter Functionality

03:21:28

Creating Anonymous Functions

03:25:05

Mapping Filters

03:29:04

Applying Filters on Images

03:33:23

Building Transform Image Method

03:36:09

Creating the Transform Image Method

03:38:54

Connecting Lambda Methods to Buttons

03:40:19

Running the Image Editing App

03:43:41

Overview of the Expense Tracker App

03:47:01

Designing the Expense Tracker Layout

03:52:31

Designing the Expense Tracker Interface

03:52:53

Adding Buttons for Expense Actions

03:53:27

Integrating SQL Database into the App

03:53:31

Setting Up Q Table Widget

03:55:44

Creating a Master Layout

04:09:15

Creating Database Tables

04:09:24

Setting Up the ID Column

04:09:32

Understanding Column Data Types

04:09:51

Executing SQL Queries in PiQT

04:11:00

Initializing Methods for Database Operations

04:25:52

Creating the Database Structure

04:25:59

Understanding Primary Keys in SQL

04:26:06

Setting Up Expense Data Types

04:27:22

Loading Data into Q Table Widget

04:35:57

Implementing the Load Table Method

04:42:31

Preparing Database Query

04:43:13

Binding Values to Query

04:44:03

Clearing Input Fields

04:45:15

Setting Current Date

04:46:18

Loading New Database Data

04:59:10

Implementing Confirmation Dialogs

05:00:39

Preparing SQL Delete Queries

05:01:31

Executing SQL Delete Operations

05:01:49

Connecting Delete Functionality to UI

05:03:17

Finalizing the Expense Tracker App

05:15:53

Styling with CSS in PiQT

05:16:57

Introduction to the Interest Rate Calculator App

05:17:41

Understanding App Functionality

05:18:29

Description of Widgets in App

05:20:54

Layout Design for the Interest Rate Calculator

05:32:32

Setting Up Interest Calculation

05:41:46

Creating the Interest Calculation Method

05:43:44

Implementing Error Handling

05:46:14

Formatting the Interest Output

05:48:06

Connecting Buttons to Functions

05:49:14

Updating the Interest Calculator Design

05:49:49

Introduction to Data Visualization

05:50:44

Using Matplotlib for Charts

05:54:08

Creating Subplots in Matplotlib

06:05:54

Updating the Interest Calculation Chart

06:07:01

Creating Years List for Chart

06:09:16

Calculating Investment Growth

06:11:46

Preparing Data for CSV and Chart Saving

06:22:30

Saving Data to CSV Files

06:25:00

Implementing Save Functionality

06:28:40

Adding Dark Mode Feature

06:33:15

Styling the Application

06:39:10

Conclusion and Course Wrap-Up

06:40:17

Celebrating Your Progress

06:40:51

Skill Development Reflection

06:41:44

Next Steps in Learning

01:00

What are the five interactive apps we'll build in this course?

10:42

How does PiQT bridge C++ and Python for app development?

13:12

What makes PiQT suitable for cross-platform applications?

14:47

Why avoid using QT Designer for building PiQT apps?

16:01

What are the key components of a windowed application in PiQT?

20:14

How can the PiQT modules enhance our app development process?

29:56

What methods will you frequently use with QT classes?

18:10

How do rows and columns shape the app design?

32:46

Why is camel casing crucial in PiQT app development?

33:25

How do we structure the app layout with rows and columns?

33:56

What essential code is needed to set up a main window in our app?

35:40

How can you customize the title and size of your app window?

49:30

How does the click event work in PiQT applications?

53:09

What are the benefits of building designs with multiple rows and columns?

57:43

How can the Python random module enhance your app's functionality?

01:04:58

What is the significance of the QGrid Layout in designing a calculator?

01:07:33

How can we effectively handle repetitive tasks in coding with loops?

01:06:46

What is the purpose of the Q line edit in our calculator app design?

01:07:50

How do we implement a loop to create multiple buttons efficiently?

01:22:09

What does the finalized layout of our calculator app look like?

01:23:55

What is the main function structure for button events in our app?

01:26:11

How does the Eval function simplify expression evaluation in Python?

01:29:19

What happens if a user tries to divide by zero in our calculator?

01:30:32

How can CSS be used to enhance the aesthetics of our calculator app?

01:39:24

How does refactoring improve our calculator app's structure?

01:39:42

What are the benefits of using classes in PiQT applications?

01:48:24

How can QFont enhance your app's text readability and design?

01:55:08

What widgets are essential for building a photo editing app?

01:55:58

How can Q labels prepare your app's design for images?

01:56:34

What layout strategies can enhance the design of our app?

01:59:15

What initial widgets do we need for our photo editing app?

02:13:11

How can you quickly convert an image to black and white using Pillow?

02:14:26

What steps are necessary to add sharpness or color to an image in Python?

02:17:26

How does saving images with the Pillow library work when editing photos?

02:29:41

How can we effectively filter files by their extensions?

02:32:51

What methods help us access and display images in PiQT?

02:34:24

Why do we need unique paths for saving images?

02:45:55

What is the role of QFileDialog in managing directories?

02:46:50

How do you filter file extensions for image loading in your app?

02:51:11

How does the Editor class manage image loading and saving?

03:04:59

How does our app load and display selected images dynamically?

03:09:24

What happens when we convert an image to black and white?

03:14:09

What are lambda functions and how can they simplify our filter implementation?

03:24:20

How do black and white filters transform images in Python?

03:26:25

What role do anonymous functions play in applying filters?

03:30:13

How can you dynamically change filters with dropdown selections?

03:36:09

How does the transform image method simplify code efficiency?

03:41:41

What are the new functionalities being introduced in our image app?

03:44:03

What widgets will we use in the expense tracking app design?

03:53:46

What key components will we display in the expense tracker table?

03:56:34

How do we dynamically add row layouts in PiQT?

04:04:58

What is the SQL setup needed for our expense tracking app?

04:09:19

How do we set up columns in our expense database table?

04:11:22

What methods will be used for adding and deleting data in our database?

04:12:46

How does the loop work when loading data from the database?

04:26:06

What are the essential data types for the expense table in SQL?

04:25:57

How does SQL handle auto-increment for primary keys?

04:27:20

What steps are involved in loading data from the database to the UI?

04:42:43

How do we prepare to insert values into our database table?

04:43:23

What steps are taken to bind input values to the SQL query?

04:44:07

How can we clear input fields for the next expense entry?

04:59:27

How does the confirm dialog enhance user experience during deletion?

05:00:42

What SQL syntax is crucial for safely deleting expense entries?

05:01:40

How do we verify the updated data loading in our application?

05:16:16

How does CSS enhance the appearance of our apps?

05:17:04

What features will the interest rate calculator include?

05:18:33

How are widgets in the app designed for user interaction?

05:32:59

How can user input errors affect interest calculations?

05:33:08

What steps are needed to visualize interest data in the app?

05:47:34

How does the reset button improve user interaction?

05:49:54

How can you visually represent your interest calculations using Python?

05:51:57

What is the significance of Figure Canvas when using Matplotlib with PiQT?

05:58:03

How does list comprehension simplify creating interest over the years?

06:06:11

How can we dynamically update our interest chart with new data?

06:07:50

What role does list comprehension play in calculating investment totals over time?

06:12:14

How do we save both CSV data and chart images in our application?

06:22:30

How do we save app results into a CSV file successfully?

06:25:36

What are the steps to test the save functionality in the app?

06:28:54

Can we implement a dark mode feature in our application?

06:40:42

How did the course bridge concepts from C++ to Python?

06:41:28

What powerful skills have you gained for future projects?

06:42:00

Why is it essential to reflect on what you've learned?


SQLDatabaseData and information visualizationSoftware developmentInheritance (object-oriented programming)Python (programming language)Tree structureSoftware frameworkTable (information)Application softwareMobile app developmentGraphical user interfaceLayout managerMap projection

Description

This content delves into building desktop applications using Python, specifically focusing on graphical user interfaces (GUIs). The core technologies in Python, such as the PiQD framework and SQL integration, are explored throughout the process. Participants will learn how to build five interactive applications using Python, which is ideal for beginners looking to enhance their skills in this area. The content covers essential tools and frameworks that are crucial for GUI development with Python. It's designed for those who want to take their Python knowledge up a level and explore its capabilities in creating GUIs.