<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Verdana;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Verdana",sans-serif;
        color:#001A6C;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:13.0pt;font-family:"Verdana",sans-serif;color:#001A6C">Nice Matt!<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:13.0pt;font-family:"Verdana",sans-serif;color:#001A6C"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:13.0pt;font-family:"Verdana",sans-serif;color:#001A6C">Thanks for taking the time to code it up!  It’s great to see examples like these.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:13.0pt;font-family:"Verdana",sans-serif;color:#001A6C"><o:p> </o:p></span></p>
<p class="MsoNormal"><i><span style="font-size:13.0pt;font-family:"Verdana",sans-serif;color:#001A6C"><a href="mailto:mike_barnett@hotmail.com"><span style="color:#0563C1">@mike</span></a><o:p></o:p></span></i></p>
<p class="MsoNormal"><span style="font-size:13.0pt;font-family:"Verdana",sans-serif;color:#001A6C"><o:p> </o:p></span></p>
<p class="MsoNormal"><b>From:</b> Python-ideas <python-ideas-bounces+mike_barnett=hotmail.com@python.org>
<b>On Behalf Of </b>Matthew Einhorn<br>
<b>Sent:</b> Friday, August 24, 2018 7:51 PM<br>
<b>To:</b> python-ideas@python.org<br>
<b>Subject:</b> Re: [Python-ideas] A GUI for beginners and experts alike<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal">Hi Mike<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I'm not sure this thread is python-ideas appropriate, but since the challenge is out, here it is using Kivy. The code and result is at
<a href="https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgist.github.com%2Fmatham%2F45c4f1fbd8c3fccf6557b3b48356cd50&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345906031&sdata=Uwr%2FzUCh17hCHSpIsTzA36iVmFpkE%2FgWb7i8DeABhik%3D&reserved=0">
https://gist.github.com/matham/45c4f1fbd8c3fccf6557b3b48356cd50</a> (image <a href="https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgist.githubusercontent.com%2Fmatham%2F45c4f1fbd8c3fccf6557b3b48356cd50%2Fraw%2Fdbbf74f17ad4beab49f022bbf43fcc72ff725084%2Fkivy_gui.png&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345916042&sdata=s22vKrCMVzvL76RNm%2FQtU9sJMafFp%2By3i1ZQqD3167E%3D&reserved=0">
https://gist.githubusercontent.com/matham/45c4f1fbd8c3fccf6557b3b48356cd50/raw/dbbf74f17ad4beab49f022bbf43fcc72ff725084/kivy_gui.png</a>). The code is also inlined below.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I wrote it to be one file so I used the string version (load_string) for defining the GUI, but the GUI definition could have been written as a separate kv file. I could also have written it using pure python, but that is more verbose and
 less intuitive. Also, Kivy works on pretty much all platforms (windows, linux, osx, android, ios) and is written in pure python (and cython) on top of opengl.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">All the best,<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">Matt<o:p></o:p></p>
</div>
<div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">P.S. here's the inlined code:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt">from kivy.lang import Builder<br>
from kivy.app import runTouchApp<br>
<br>
runTouchApp(Builder.load_string('''<br>
#:import Factory kivy.factory.Factory<br>
BoxLayout:<br>
    orientation: 'vertical'<br>
    padding: "12dp"<br>
    spacing: "12dp"<br>
    Label:<br>
        text: "Please enter 3 numbers"<br>
    BoxLayout:<br>
        spacing: "10dp"<br>
        Entry:<br>
            id: a<br>
            hint_text: "A"<br>
        Entry:<br>
            id: b<br>
            hint_text: "B"<br>
        Entry:<br>
            id: c<br>
            hint_text: "C"<br>
    Label:<br>
        text: "The sum is {}".format(a.val + b.val + c.val)<br>
            <br>
<br>
<Entry@TextInput>:<br>
    input_filter: "float"<br>
    val: float(self.text) if self.text else 0<br>
'''))<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal">On Fri, Aug 24, 2018 at 5:28 PM Clément Pit-Claudel <<a href="mailto:cpitclaudel@gmail.com">cpitclaudel@gmail.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<p class="MsoNormal">Hi Mike,<br>
<br>
Thanks, this code is nice and short.  Is adding 'if button is None: break' to the 'Read' version of your code the right way to make it exit when the main window is closed? (On my machine it enters an infinite loop after I close the main window).<br>
<br>
For comparison, I tried doing this with PyGObject.<br>
I created the UI with glade, which auto-generated the attached XML file.  Then I had to write the following code (I had never used Glade or PyGObject before, so apologies if there are mistakes in the following):<br>
<br>
import gi<br>
gi.require_version('Gtk', '3.0')<br>
from gi.repository import Gtk<br>
<br>
def main():<br>
    builder = Gtk.Builder()<br>
    builder.add_from_file("sum.glade")<br>
<br>
    get = builder.get_object<br>
    a, b, answer, window = get("a"), get("b"), get("answer"), get("window")<br>
<br>
    def update_sum(_entry):<br>
        try:<br>
            tanswer = int(a.get_text()) + int(b.get_text())<br>
            answer.set_text(str(tanswer))<br>
        except ValueError:<br>
            pass<br>
<br>
    a.connect("changed", update_sum)<br>
    b.connect("changed", update_sum)<br>
    window.connect("destroy", Gtk.main_quit)<br>
<br>
    window.show_all()<br>
    Gtk.main()<br>
<br>
if __name__ == '__main__':<br>
    main()<br>
<br>
Having a visual editor for the UI feels like a plus, and I find the resulting XML verbose but acceptably readable.<br>
On the other hand, I like the conciseness of your UI specs.<br>
<br>
Cheers,<br>
Clément.<br>
<br>
On 2018-08-24 16:38, Mike Barnett wrote:<br>
> I should have mentioned that you need the GitHub version of the code in order to get the keyboard events. Rather than do a pip install you can download this file and put it in your project folder:<br>
> <br>
> <a href="https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FMikeTheWatchGuy%2FPySimpleGUI%2Fblob%2Fmaster%2FPySimpleGUI.py&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345926047&sdata=9XBPgby1X5GAJo%2BPTt4RVWzAtHxN0rjN2MfSw9ycKv0%3D&reserved=0" target="_blank">
https://github.com/MikeTheWatchGuy/PySimpleGUI/blob/master/PySimpleGUI.py</a><br>
> <br>
> Sorry for any confusion.<br>
> <br>
> I also got a question if this code blocks or is in a spin-loop.   The answer is that the posted version blocks until some kind of form input.  Should you want to turn the program into one that polls instead of blocks,  the loop changes slightly to enable
 form close detection.  It's basically the same with the Read call being replaced by ReadNonBlocking.<br>
> <br>
> while True:<br>
>     button, values = form.ReadNonBlocking()<br>
>     if button is None and values is None:<br>
>         break<br>
>     a, b = values<br>
>     try:<br>
>         output.Update(int(a) + int(b))<br>
>     except:<br>
>         pass<br>
> <br>
> <br>
> <br>
> @mike<br>
> <br>
> -----Original Message-----<br>
> From: Mike Barnett <<a href="mailto:mike_barnett@hotmail.com" target="_blank">mike_barnett@hotmail.com</a>>
<br>
> Sent: Friday, August 24, 2018 3:36 PM<br>
> To: Chris Angelico <<a href="mailto:rosuav@gmail.com" target="_blank">rosuav@gmail.com</a>>; Python-Ideas <<a href="mailto:python-ideas@python.org" target="_blank">python-ideas@python.org</a>><br>
> Subject: RE: [Python-ideas] A GUI for beginners and experts alike<br>
> <br>
> <br>
> So here's my alternative challenge:<br>
> <br>
> Take two numbers as inputs. Add them together and display them in a third field. Whenever either input is changed, recalculate the output.<br>
> <br>
> This requires proper event handling, so it's less likely to create a useless one-liner that has no bearing on real-world code.<br>
> <br>
> ------------------------------------<br>
> <br>
> <br>
> <br>
> Sure thing... post yours. I'll go ahead and post mine first.<br>
> <br>
> Here's the window this code produces.<br>
> <br>
> <a href="https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fuser-images.githubusercontent.com%2F13696193%2F44604157-02a2ac00-a7b3-11e8-928b-f67c5f2b3961.jpg&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345936052&sdata=92w%2FrRVX5i05EC%2BaUrhYGVpUfF0XSwg8%2B1cLnC3Fn9c%3D&reserved=0" target="_blank">
https://user-images.githubusercontent.com/13696193/44604157-02a2ac00-a7b3-11e8-928b-f67c5f2b3961.jpg</a><br>
> <br>
> And here's the code in a more readable form since the email formatting sucks.<br>
> <a href="https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fuser-images.githubusercontent.com%2F13696193%2F44604220-2cf46980-a7b3-11e8-86c5-ad3051222eaf.jpg&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345946081&sdata=CyGFT%2F7%2FycMstybAAirly4GHFlfqSnoVNy93LWUxvdw%3D&reserved=0" target="_blank">
https://user-images.githubusercontent.com/13696193/44604220-2cf46980-a7b3-11e8-86c5-ad3051222eaf.jpg</a><br>
> <br>
> It's rather, uhm, simple to do....<br>
> <br>
> <br>
> import PySimpleGUI as gui<br>
> <br>
> output = gui.Text('')<br>
> <br>
> layout = [ [gui.Text('Enter 2 numbers')],<br>
>            [gui.Text('A'), gui.InputText()],<br>
>            [gui.Text('B'), gui.InputText()],<br>
>            [gui.Text('Answer = '), output],<br>
>            ]<br>
> <br>
> form = gui.FlexForm('Realtime Updates', return_keyboard_events=True)<br>
> form.LayoutAndRead(layout)<br>
> while True:<br>
>     button, (a,b) = form.Read()<br>
>     try:<br>
>         answer = int(a) + int(b)<br>
>         output.Update(answer)<br>
>     except:<br>
>         pass<br>
> <br>
> <br>
> @mike<br>
> _______________________________________________<br>
> Python-ideas mailing list<br>
> <a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
> <a href="https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmail.python.org%2Fmailman%2Flistinfo%2Fpython-ideas&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345956086&sdata=c3rmX6G8AcyDmHRG%2B%2BkQ8We1OgF0mJ0RVSCJLYdB%2FLY%3D&reserved=0" target="_blank">
https://mail.python.org/mailman/listinfo/python-ideas</a><br>
> Code of Conduct: <a href="https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fpython.org%2Fpsf%2Fcodeofconduct%2F&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345966097&sdata=xSinnBACOmIv4y2Z8AQLGL7sxjjBts84L%2BEkWfBC68A%3D&reserved=0" target="_blank">
http://python.org/psf/codeofconduct/</a><br>
> <br>
<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmail.python.org%2Fmailman%2Flistinfo%2Fpython-ideas&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345986107&sdata=l0h7XMzPGMOBsm%2F7XOzlPkPgCgKHPJLY9iJDam1KhAk%3D&reserved=0" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fpython.org%2Fpsf%2Fcodeofconduct%2F&data=02%7C01%7C%7Ce79abd06c77544c33e7008d60a1c9d95%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636707515345996112&sdata=34iqzRJ7AfpiElm07U9HGv8sqvgzkwOuOxDj6tDQztk%3D&reserved=0" target="_blank">
http://python.org/psf/codeofconduct/</a><o:p></o:p></p>
</blockquote>
</div>
</div>
</body>
</html>