Attractive GUIs with PySimpleGUI
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Ham, Ruud van der
In the Python landscape, there are several high-end GUI packages. Of course, there’s tkinter which is part of the standard library. And there is wxPython and several versions of Qt. What they share is that they are very flexible but not only have a steep learning curve but also take considerable development effort to realize even a simple user interface. At the other of the spectrum, there are several design tools that either generate code of a layout structure. In many cases, the functionality is rather limited, though. Relatively recent, an independent open-source developer (not me) has made a product that tries to bridge the gap between these two worlds: PySimpleGUI. This package runs on top of tkinter, QT for Windows, wxPython and Remi. In this talk, I want to show the design methodology behind this fascinating product that might change the way people look at GUIs. I will start with live coding a simple yet not evident program that shows the basic concepts. With this, I will demonstrate the design philosophy. PySimpleGUI can also be used to implement a user-friendly interface as opposed to command-line interfaces. From there, I will give an overview of some more elements present in this package. Finally, I will show a full-featured GUI program with several bells and whistles.
 Well, today I would like to talk about a GUI package called PySynCooL GUI. Let me just show my interest, why I'm interested in PySynCooL GUI. I had some experience with animation, quite technical in Tika Inter, because I have a kind of simulation package. But then I also had some project that could use an attractive GUI. My first idea was then Tika Inter, but that's quite tricky. And then I had practically no experience with those GUIs. And then I got into contact with the sole developer and maintainer of this PySynCooL GUI package through a forum. I joined regularly and I thought, well, this is a good start. But you have to remember, I'm not really a GUI expert. I just wanted to show you what I found and I would do some live coding, just building one or two small projects. So what's on the menu for today, just some short introduction with GUIs. What is PySynCooL GUI? I want to do, if possible, two sample applications, show you a little bit of what PySynCooL can do with the work from others, some pros and cons, and then a conclusion. So why GUIs? Well, they're important because, well, if you just have a text interface, it doesn't really work. It's complicated and just for simple tasks can be already very interesting to have the pretty interface. But GUIs are usually quite complicated. They take time to set up and you have to know a lot of things. And that's why it's sometimes not very attractive to start with that. So for instance, a very small GUI, more or less, trivial thing, because we have the input function. So we just ask for a number and another number and we just add it up and then we have a certain time. Well, this is not very attractive, of course. There's absolutely nothing there. Another example of non-GUI application is a command line interface. For instance, black, the deformator. If you want to run that one from the command line, you have a number of options and you have to remember all the formats and all that. So it's also not very attractive. It would be nice to have a kind of interface for that. And we're going to work on that. What's there in the Python world? One of the most obvious is TK-inter, which comes standard with most Python installation. It has a lot of features, maybe a bit old-fashioned, but it's very flexible, but has a high learning curve and a not very intuitive API. Just to show you that, here's just a very small example of an application. I'm asking for two numbers to add them up. But there you have already quite a lot of code. Not that obvious. You have to do something here to define a route, but you have to start a main loop, something with grids, and there's callback options. So this is not that easy, actually, to do. I'll show you the same applications in a couple of minutes in TK-inter. Then there are other GUI frameworks. The most well-known are WX Python, PyQt, SkyVee, which is interesting because that's also cross-platform. But all of them have actually this quite long learning curve. They are powerful, and some of them even incur license costs, for instance, PyQt. And there are some GUI builders for interactive systems. They're not very popular in the Python world, maybe because the interfacing is rather complex. And you have to maintain both the GUI part, which is usually done in a graphical interface and the application. Some of the examples are Page and PyQBoo. Not even sure whether they're well maintained or not. So then there's an alternative called PySyntwo GUI, which is a relatively new project started two years ago. It's extremely actively maintained, which means that there are new versions very, very frequently released. It's open source. And what's the interesting thing is that it runs actually under or on four different platforms, available on TKinter, which is actually the main branch that's PyQt. PyQt, there's WXpython. And this is also interesting. You can also make a web interface. And in principle, they have all the same API. I want to do something with the TKinter version of PySyntwo GUI. And therefore, I'm going to switch to PySyntwo now. So what I want to do is build this simple adder application, which has two numbers and results, calculate button here, and we're going to build it. So it starts really from scratch. So the first thing you have to do is import PySyntwo GUI as G. That's a quite good convention. Then we say... See, that's also the Qt version. Then we go and define those rows. And those rows are actually just defined as a list of all the elements that are in there. So what's there? We start with a text field. And the text field is, of course, the title, the name, number one. Then we have an input field. And the input field needs to be identified later. So I just have to give it what they call a key. And so that's the second field. The third field is a button with the name, with the title CalcQ. Okay, that's row one. Now row two is more or less the same, of course. So I just say row two. Just change the ones and twos. We don't have a button on this line. And then we have row three. Well, row three is actually just a... Again a text. And then followed by another field. Another text field. And that text field has to have a size because we're going to fill that later. Wait a minute, I can also do this. Easier. And then it has already a size. And then this one is a key. I have to reference to that. And the reference is then result. And that's actually it. Then I just say, okay, I want to formulate all those things which we call a layout. Layout is... And that's a list of row one, row two, and row three. Row three. And then I did make a window. And the window is actually making this whole thing. I just add a title, adder, and a layout to indicate what it looks like. And then we can already test it. And I'm sure there are some mistakes in the... Let me see. Window.read. This is just a demo. I'll just go ahead and test it. It's very slow for some reason. Still make a mistake, comma. Real life confidence. You always people who shout, make a mistake. But that's not possible now. I'm afraid. Window is not defined. Okay, well, it doesn't do anything. Here you can see actually already whole layout and all that. But it doesn't do anything yet because I haven't defined anything. But I'm going to replace this with a small event loop file too. You will always. Then I just read this window. Returns an event and some failures. And then I just say event is window. In that case, we're done. So we break. And otherwise, we just go and say event. Yes. And then you just get the name of the bit. Calculate. In this case, this is the only action that can cause an event. Then we can just get the number. So we say number one. Number one is the integer of and then we read the, this, this field here, which is done. Thank you. And then we just, this is the, we just say values of number one because those are all strings. We just do the next line. Same story. So now we have the two numbers. Just heading them up. Two. And then we just, we just want to display them. Then you do that by window and then I look up this value results. This is this key, this field. I just say results.update. Results. And then that should work. Yeah. So now I can just show you that it works 10 plus 33 is not correct. I'm sorry. It's a slow. I must have to do with the zoom connection at the same time. Okay. Okay. And now it's problem here and I want to show you something if I just say an invalid value value. And then I can just show you some of the other features. Then I just say, okay, I want to, to check this one. And then if I get a value error. I can just do it. Because that's so easy. And I just kind of can do a pop up saying wrong. And I do something extra in this as well. I just say, okay, I want to have some nice, nice color scheme. You can just do that with, with theme. And I know there's a nice one called dark amber. And I can also just add a tool tip. Just to show you how simple that can be. I just add to tip is. Enter. Yeah. Okay. Well, just do a. You see here the pop up. And I can still run it of course. But I can just do it. You can see the tool tip. Well, this is just in, in 10 minutes. An application built. Now I want to do something else, but this is a project. Well, it is actually worth more, more useful. To do that. But you ask for a folder the line lengths, the targets, which is the kind of. It's one of the input fields of. For black. And then I can shoot. Well, I'm not going to do this a lie because that will take too much time. I think that I could just go and. it's all about this this part. So what you can see here and actually it's more or less still the same. This is that folder thing and here at the end, I'll just make this pick. Assume, but the zoom system is in the way. Oh wait, here it is done. Okay, so here we have the, we just put the browse. Well then it's that's some commands that you can search for the folders. Here's the line length and I hear the slider. So that's this one here, this slider. Then I do a with the just give some parameters. I do a combo box for the target version. Also with a key and all that. And then I do a text, a multi-line. A multi-line is this thing here, which you can put whatever text you want. And there are two buttons here. So that's these two. And all these ones are actually just the layout thing because I did it all in at once. And then there's the main loop. And the main loop is nothing more than the notice just saw if the event is black. And then we do something which is a bit complicated but the interesting with the black system, which is a process. And then let me just run this. You can see that's already quite an interesting and attractive GUI to a complicated command line. And this is well just just a minute matter of a couple of minutes, of course. And here you see, well, I've got a black thing, of course. And I can just say, okay, I want to browse. Then you get a browse folder automatically. You don't have to do anything about that. I just say, okay, I want to have a folder. And then let me just do this one. This one. And then I just select that folder. You can see that here I can just play with the line length. I can play here with the target version. And then I just say, okay, do it. Now in the background, it's running this subprocess to run black, which takes time apparently. Yeah, I put should appear here in this window. But the whole system is not as slow. So, yeah, well, in this case, there's nothing, it just says all done. This is output from black. All done, two left, two files left unchanged. And I get a popup here, which is just given here. And then we don't. So there's also a very simple, quickly built interface, but you can go much further than that. And that's what I want to show you now. For instance, where this is actually quite, quite, quite easy. This is actually an example of an application I built on to run on an Android phone. Just also with the same, the same version, PysynBugui interface. This is something to create a lockdown document here in France. And now I just want to show you some of the application from the site. Some interesting things. The interface with mudplotlib. And then you can just, this is all done in PysynBugui. You can just select all kinds of things. This is an example of a crossword puzzle. I think this I do it done with buttons. I'm not actually sure how this is done. But that's also one of the users who made this one. This is an interesting one. This is an application that's actually an open CV connection in which is actually kind of traffic camera, apparently something with this stolen car. So I don't know what is exactly, but this is a real application that someone made. You see all the different widgets that are available. Of course, it's much more available than it is to use everything, spin boxes and really other things. So to conclude, well, first of all, I am by far not the PysynBugui experts. I just know a fraction of the functionality, but I can already do quite a lot of things with it. It has really a lot of widgets and features interfaces with open speccasures. Of course, there's more or less something that's given by Pysyn, of course, support threading, which is not obvious. That's quite often very complicated. It is cross platform, which means that the different versions are more or less the same, not 100% the same. And one of the interesting ports is definitely the WebRuby interface. The documentation is really super. It's a whole set of documentation with reference guides and it's a good cookbook and all that better than a lot of the queries themselves. So it's great for beginners, that's for sure, but also experts who don't want to spend that much time, for instance, to when you have a command line interface. Then it's a very nice thing to do, a nice thing to have. But of course, there are pre-packaged solutions, many, but customization. You can customize nearly all the calls, but still there are limitations. So you can't control everything. And something also to consider is that this package is developed by just one man. And so continuity, well, I don't know. So to conclude, actually, I want to say PySynPokui is a very attractive package. Where's the give it a try? And I would say go to his website, PySynPokui.com, and then you will find out yourself. You can find out yourself and then you won't be disappointed, I think. And then I would like to thank you for your attention. And well, if there are any questions, I'm here to answer them. Thanks, Pruth. There is one question here from Matthew. A really nice demonstration. Do you have any recommendations on when PySynPokui might be insufficient and you need to go with one of the more powerful libraries like Tkinten? Yeah, I think particularly if you have, if there's really to be high end, and you want really full control over all the placement of widgets, and you want to do more things with callbacks in which you have to react on all kinds of actions at the same time. This package is particularly good in the things that they defined. But I can imagine that you can't really do everything in it. But as I said before, I'm not really a very gooey expert, but I understand that certain things can't be done with packages like that. But I also understand that at least you can escape to the ordinary version. So if you run PySynPokui under Tkint, for instance, you can still break into the main loop. I don't know how, but that seems to be possible. Great. Thanks. Metatux is asking, does Remy serve a web server or is the output an HTML file with JavaScript? As far as I know, it's close to Remy. And then you can see immediately the output. It's really a gooey in the web. I'm not sure how, you have to have a look at Remy. And I don't know anything about Remy. I just know that there's an interface for that. And it seems some very nice demonstrations of it. All right. And we have another one, which is very new to Python, programming Linux, applying this in a Linux environment. Is it as simple as Windows? I guess, is this cross-platform? Absolutely. Absolutely. And actually, I think most of it is actually developed in Linux. I'm a Windows user, but I've used it also on Raspberry Pi in Linux. No problem at all. Mac OS is okay. And so the only thing which doesn't support it, I'm a PySynista, this is an iPad application. And there you can't use it because there's no TTA interface. No. For me, it's still a problem. All right. Thanks, Wirt. I'm representing everyone watching. Okay. Flash up.
 Well, today I would like to talk about a GUI package called PySynCooL GUI.  Let me just show my interest, why I'm interested in PySynCooL GUI.  I had some experience with animation, quite technical in Tika Inter, because I have a  kind of simulation package.  But then I also had some project that could use an attractive GUI.  My first idea was then Tika Inter, but that's quite tricky.  And then I had practically no experience with those GUIs.  And then I got into contact with the sole developer and maintainer of this PySynCooL  GUI package through a forum.  I joined regularly and I thought, well, this is a good start.  But you have to remember, I'm not really a GUI expert.  I just wanted to show you what I found and I would do some live coding, just building  one or two small projects.  So what's on the menu for today, just some short introduction with GUIs.  What is PySynCooL GUI?  I want to do, if possible, two sample applications, show you a little bit of what PySynCooL can  do with the work from others, some pros and cons, and then a conclusion.  So why GUIs?  Well, they're important because, well, if you just have a text interface, it doesn't  really work.  It's complicated and just for simple tasks can be already very interesting to have the  pretty interface.  But GUIs are usually quite complicated.  They take time to set up and you have to know a lot of things.  And that's why it's sometimes not very attractive to start with that.  So for instance, a very small GUI, more or less, trivial thing, because we have the input  function.  So we just ask for a number and another number and we just add it up and then we have a certain  time.  Well, this is not very attractive, of course.  There's absolutely nothing there.  Another example of non-GUI application is a command line interface.  For instance, black, the deformator.  If you want to run that one from the command line, you have a number of options and you  have to remember all the formats and all that.  So it's also not very attractive.  It would be nice to have a kind of interface for that.  And we're going to work on that.  What's there in the Python world?  One of the most obvious is TK-inter, which comes standard with most Python installation.  It has a lot of features, maybe a bit old-fashioned, but it's very flexible, but has a high learning  curve and a not very intuitive API.  Just to show you that, here's just a very small example of an application.  I'm asking for two numbers to add them up.  But there you have already quite a lot of code.  Not that obvious.  You have to do something here to define a route, but you have to start a main loop, something  with grids, and there's callback options.  So this is not that easy, actually, to do.  I'll show you the same applications in a couple of minutes in TK-inter.  Then there are other GUI frameworks.  The most well-known are WX Python, PyQt, SkyVee, which is interesting because that's  also cross-platform.  But all of them have actually this quite long learning curve.  They are powerful, and some of them even incur license costs, for instance, PyQt.  And there are some GUI builders for interactive systems.  They're not very popular in the Python world, maybe because the interfacing is rather complex.  And you have to maintain both the GUI part, which is usually done in a graphical interface  and the application.  Some of the examples are Page and PyQBoo.  Not even sure whether they're well maintained or not.  So then there's an alternative called PySyntwo GUI, which is a relatively new project started  two years ago.  It's extremely actively maintained, which means that there are new versions very, very  frequently released.  It's open source.  And what's the interesting thing is that it runs actually under or on four different platforms,  available on TKinter, which is actually the main branch that's PyQt.  PyQt, there's WXpython.  And this is also interesting.  You can also make a web interface.  And in principle, they have all the same API.  I want to do something with the TKinter version of PySyntwo GUI.  And therefore, I'm going to switch to PySyntwo now.  So what I want to do is build this simple adder application, which has two numbers and  results, calculate button here, and we're going to build it.  So it starts really from scratch.  So the first thing you have to do is import PySyntwo GUI as G. That's a quite good convention.  Then we say...  See, that's also the Qt version.  Then we go and define those rows.  And those rows are actually just defined as a list of all the elements that are in there.  So what's there?  We start with a text field.  And the text field is, of course, the title, the name, number one.  Then we have an input field.  And the input field needs to be identified later.  So I just have to give it what they call a key.  And so that's the second field.  The third field is a button with the name, with the title CalcQ.  Okay, that's row one.  Now row two is more or less the same, of course.  So I just say row two.  Just change the ones and twos.  We don't have a button on this line.  And then we have row three.  Well, row three is actually just a...  Again a text.  And then followed by another field.  Another text field.  And that text field has to have a size because we're going to fill that later.  Wait a minute, I can also do this.  Easier.  And then it has already a size.  And then this one is a key.  I have to reference to that.  And the reference is then result.  And that's actually it.  Then I just say, okay, I want to formulate all those things which we call a layout.  Layout is...  And that's a list of row one, row two, and row three.  Row three.  And then I did make a window.  And the window is actually making this whole thing.  I just add a title, adder, and a layout to indicate what it looks like.  And then we can already test it.  And I'm sure there are some mistakes in the...  Let me see.  Window.read.  This is just a demo.  I'll just go ahead and test it.  It's very slow for some reason.  Still make a mistake, comma.  Real life confidence.  You always people who shout, make a mistake.  But that's not possible now.  I'm afraid.  Window is not defined.  Okay, well, it doesn't do anything.  Here you can see actually already whole layout and all that.  But it doesn't do anything yet because I haven't defined anything.  But I'm going to replace this with a small event loop file too.  You will always.  Then I just read this window.  Returns an event and some failures.  And then I just say event is window.  In that case, we're done.  So we break.  And otherwise, we just go and say event.  Yes.  And then you just get the name of the bit.  Calculate.  In this case, this is the only action that can cause an event.  Then we can just get the number.  So we say number one.  Number one is the integer of and then we read the, this, this field here, which is done.  Thank you.  And then we just, this is the, we just say values of number one because those are all  strings.  We just do the next line.  Same story.  So now we have the two numbers.  Just heading them up.  Two.  And then we just, we just want to display them.  Then you do that by window and then I look up this value results.  This is this key, this field.  I just say results.update.  Results.  And then that should work.  Yeah.  So now I can just show you that it works 10 plus 33 is not correct.  I'm sorry.  It's a slow.  I must have to do with the zoom connection at the same time.  Okay.  Okay.  And now it's problem here and I want to show you something if I just say an invalid value  value.  And then I can just show you some of the other features.  Then I just say, okay, I want to, to check this one.  And then if I get a value error.  I can just do it.  Because that's so easy.  And I just kind of can do a pop up saying wrong.  And I do something extra in this as well.  I just say, okay, I want to have some nice, nice color scheme.  You can just do that with, with theme.  And I know there's a nice one called dark amber.  And I can also just add a tool tip.  Just to show you how simple that can be.  I just add to tip is.  Enter.  Yeah.  Okay.  Well, just do a.  You see here the pop up.  And I can still run it of course.  But I can just do it.  You can see the tool tip.  Well, this is just in, in 10 minutes.  An application built.  Now I want to do something else, but this is a project.  Well, it is actually worth more, more useful.  To do that.  But you ask for a folder the line lengths, the targets, which is the  kind of.  It's one of the input fields of.  For black.  And then I can shoot. Well, I'm not going to do this a lie because  that will take too much time.  I think that I could just go and.  it's all about this this part. So what you can see here and actually it's more or less still the  same. This is that folder thing and here at the end, I'll just make this pick.  Assume, but the zoom system is in the way. Oh wait, here it is done.  Okay, so here we have the, we just put the browse. Well then it's that's some commands  that you can search for the folders. Here's the line length and I hear the slider. So that's this  one here, this slider. Then I do a with the just give some parameters. I do a combo box for the  target version. Also with a key and all that. And then I do a text, a multi-line. A multi-line is  this thing here, which you can put whatever text you want. And there are two buttons here.  So that's these two. And all these ones are actually just the layout thing because I did  it all in at once. And then there's the main loop. And the main loop is nothing more than  the notice just saw if the event is black. And then we do something which is a bit complicated  but the interesting with the black system, which is a process. And then let me just run this.  You can see that's already quite an interesting and attractive GUI to a complicated  command line. And this is well just just a minute matter of a couple of minutes, of course. And  here you see, well, I've got a black thing, of course. And I can just say, okay, I want to browse.  Then you get a browse folder automatically. You don't have to do anything about that.  I just say, okay, I want to have a folder. And then let me just do this one. This one.  And then I just select that folder. You can see that here I can just play with the line length.  I can play here with the target version. And then I just say, okay, do it. Now in the background,  it's running this subprocess to run black, which takes time apparently.  Yeah, I put should appear here in this window. But the whole system is not as slow.  So, yeah, well, in this case, there's nothing, it just says all done. This is output from black.  All done, two left, two files left unchanged. And I get a popup here, which is just given here.  And then we don't. So there's also a very simple, quickly built interface, but you can go much  further than that. And that's what I want to show you now. For instance, where this is  actually quite, quite, quite easy. This is actually an example of an application I built  on to run on an Android phone. Just also with the same, the same  version, PysynBugui interface. This is something to create a lockdown document here in France.  And now I just want to show you some of the application from the site. Some interesting  things. The interface with mudplotlib. And then you can just, this is all done in PysynBugui.  You can just select all kinds of things. This is an example of a crossword puzzle. I think  this I do it done with buttons. I'm not actually sure how this is done. But that's also one of  the users who made this one. This is an interesting one. This is an application that's actually an  open CV connection in which is actually kind of traffic camera, apparently something with  this stolen car. So I don't know what is exactly, but this is a real application that someone made.  You see all the different widgets that are available. Of course, it's much more available  than it is to use everything, spin boxes and really other things. So to conclude,  well, first of all, I am by far not the PysynBugui experts. I just know a fraction of the  functionality, but I can already do quite a lot of things with it. It has really a lot of widgets  and features interfaces with open speccasures. Of course, there's more or less something that's  given by Pysyn, of course, support threading, which is not obvious. That's quite often very  complicated. It is cross platform, which means that the different versions are more or less the  same, not 100% the same. And one of the interesting ports is definitely the WebRuby interface.  The documentation is really super. It's a whole set of documentation with reference guides and  it's a good cookbook and all that better than a lot of the queries themselves.  So it's great for beginners, that's for sure, but also experts who don't want to spend that much  time, for instance, to when you have a command line interface. Then it's a very nice thing to do,  a nice thing to have. But of course, there are pre-packaged solutions, many, but customization.  You can customize nearly all the calls, but still there are limitations. So you can't control  everything. And something also to consider is that this package is developed by just one man.  And so continuity, well, I don't know. So to conclude, actually, I want to say  PySynPokui is a very attractive package. Where's the give it a try? And I would say go to his  website, PySynPokui.com, and then you will find out yourself. You can find out yourself and then  you won't be disappointed, I think. And then I would like to thank you for your attention.  And well, if there are any questions, I'm here to answer them.  Thanks, Pruth. There is one question here from Matthew. A really nice demonstration. Do you have  any recommendations on when PySynPokui might be insufficient and you need to go with one of the  more powerful libraries like Tkinten? Yeah, I think particularly if you have, if there's really  to be high end, and you want really full control over all the placement of widgets, and you want to  do more things with callbacks in which you have to react on all kinds of actions at the same time.  This package is particularly good in the things that they defined. But I can imagine that you  can't really do everything in it. But as I said before, I'm not really a very gooey expert, but  I understand that certain things can't be done with packages like that. But I also understand  that at least you can escape to the ordinary version. So if you run PySynPokui under Tkint,  for instance, you can still break into the main loop. I don't know how, but that seems to be possible.  Great. Thanks. Metatux is asking, does Remy serve a web server or is the output an HTML file with JavaScript?  As far as I know, it's close to Remy. And then you can see immediately the  output. It's really a gooey in the web. I'm not sure how, you have to have a look at Remy.  And I don't know anything about Remy. I just know that there's an interface for that. And it seems  some very nice demonstrations of it. All right. And we have another one, which is  very new to Python, programming Linux, applying this in a Linux environment. Is it as simple as  Windows? I guess, is this cross-platform? Absolutely. Absolutely. And actually, I think  most of it is actually developed in Linux. I'm a Windows user, but I've used it also on  Raspberry Pi in Linux. No problem at all. Mac OS is okay. And so the only thing which  doesn't support it, I'm a PySynista, this is an iPad application. And there you  can't use it because there's no TTA interface. No. For me, it's still a problem.  All right. Thanks, Wirt. I'm representing everyone watching. Okay. Flash up.
Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_0_347.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_348_2051.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_2052_2603.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_2604_3455.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_3456_3995.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_3996_4523.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_4524_5135.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_5136_5999.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_6000_6851.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_6852_7499.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_7500_8651.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_8652_8999.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_9000_9059.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_9060_9167.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_9168_16463.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_16464_16691.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_16692_21455.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_21456_21995.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_21996_24851.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_24852_24971.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_24972_25667.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_25668_26987.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_26988_27683.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_27684_27755.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_27756_29267.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_29268_29675.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_29676_31475.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_31476_32015.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_32016_32111.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_32112_32423.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_32424_32747.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_32748_33251.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_33252_33575.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_33576_35495.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_35496_36743.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_36744_36875.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_36876_36947.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_36948_37007.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_37008_38999.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_39000_40163.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_40164_41171.png Ruud_van_der_Ham_-_Attractive_GUIs_with_PySimpleGU_YIIlqIVBMek_41172_41509.png