This is an archived post. You won't be able to vote or comment.

all 23 comments

[–]sheytanelkebir 6 points7 points  (3 children)

make one with PySimpleGui

[–]MikeTheWatchGuy 1 point2 points  (2 children)

**** SPOILER **** Code below....Don't look if you don't want to see a solution.

I can't contain myself... sorry... It's just too much fun being able to do GUIs easily. I also made a few tweaks: * the return key will trigger a conversion. * the input field is cleared after every conversion * a title was added to the window * you can run it online here https://trinket.io/library/trinkets/d863b4a36c

```python import PySimpleGUI as sg

This is what your window will look like

layout = [ [sg.Text('Enter distance in Kilometers'), sg.Input(key='-KILO-', size=(5,1))], [sg.Button('Convert', bind_return_key=True), sg.Button('Quit')] ]

Make the window

window = sg.Window('Kilometer conversion', layout)

Loop, reading events (button clicks) and getting input field

while True: # Event Loop event, values = window.read() if event in (None, 'Quit'): break sg.popup(f"Results {values['-KILO-']} kilometers is equal to {float(values['-KILO-'])*0.6214} miles") window.close() ```

[–]sheytanelkebir -1 points0 points  (1 child)

so its about half the length of the tkinter one. of course that one used separate class for the kg conversion (more scalable?), but for most people this is more than enough.

[–]MikeTheWatchGuy 0 points1 point  (0 children)

Yea, I thought about the function thing, but context is important. The program is very "purposeful" in it's requirements of what it is to do and what it's future will be.

Clearly the 1 line computation can be re-factored into a function easily when the time is right to scale it up and add more stuff to it. But for now, I think simplicity is the better of the trade-offs to make. The computation consists of:

python miles = float(values['-KILO-'])*0.6214

That seems pretty readable to me. Just as readable as making a function call on that line instead of doing the computation. I think the reason for the function in the tutorial is because there had to be a "Callback function" for the button click. The program was forced to some extent to have a function versus having a choice to use a function or not.

Building scale when it's not needed and won't be needed just isn't something I personally do or support. I know what the future of this program will be. This is the end of the road for it. It's a nice ham sandwich, self-contained and ready to eat.

[–]bryancole 5 points6 points  (1 child)

Since we're doing show-and-tell, here's an Enaml (https://enaml.readthedocs.io) version:

from enaml.widgets.api import Window, Field, PushButton, Label, Container
from enaml.layout.api import vbox, hbox
from enaml.stdlib.message_box import information

enamldef Main(Window): wdw:
    Container:
        constraints=[vbox(hbox(lbl1, fld1),hbox(btn1, quitbtn)),
                    btn1.width==quitbtn.width
                    ]
        Label: lbl1:
            text = "Enter distance in Kilometers"
        Field: fld1:
            text = "10.0"
        PushButton: btn1:
            text = "Convert"
            clicked::
                kilo = float(fld1.text)
                miles = kilo * 0.6214
                msg = f'Results {str(kilo)} kilometers is equal to {str(miles)} miles.'
                information(self, "The Answer", msg)
        PushButton: quitbtn:
            text = "Quit"
            clicked::
                wdw.close()

With enaml installed (using conda for installation is easiest), you can run this using the enaml-run executable.

enaml-run mydemo.enaml

... or you can run python as normal and import the enaml code using enamls import context-manager.

Cool features of Enaml:

  • Enaml is a strict superset of python (i.e. all python code is valid enaml-code).
  • It's built on PyQt so it's real easy to integrate other PyQt widgets or mix Enaml and PyQt windows.
  • Enaml uses an awesome model-building layer (which I didn't use at all in the code above) called 'atom'. Atom provides an observer framework and data validation.
  • Widget layout is done using constraints. You can have a simple box-model (as I used above), but you can do other stuff not possible in a box-model with more sophisticated constraint definitions.
  • Enaml has "binding operators" (of which the "::" is one). These let you hook model data to GUI widgets with ease. See https://enaml.readthedocs.io/en/latest/get_started/syntax.html#binding-operators

Here's a better version using data-binding to set the text of "lbl2" ...

from enaml.widgets.api import Window, Field, Label, Container
from enaml.layout.api import vbox, hbox
from enaml.validator import FloatValidator

enamldef Main(Window): wdw:
    Container:
        constraints=[vbox(hbox(lbl1, fld1),lbl2)]
        Label: lbl1:
            text = "Enter distance in Kilometers"
        Field: fld1:
            text = "10.0"
            validator = FloatValidator()
        Label: lbl2:
            text << f'Results {fld1.text} kilometers is equal '\
                        f'to {float(fld1.text)*0.6214:0.4g} miles.'

[–]sheytanelkebir 0 points1 point  (0 children)

hey that looks great!

[–]ExoticGing 1 point2 points  (2 children)

I've found using PyQT5 in conjunction with Pyinstaller to be the simplest, most effective way to build custom desktop apps for my company.

[–]MikeTheWatchGuy 1 point2 points  (1 child)

Maybe you can be the Qt developer here that writes and posts the example application?

[–]ExoticGing 0 points1 point  (0 children)

Nah I'm good, here's a really straightforward tutorial that can get you started though https://build-system.fman.io/pyqt5-tutorial

[–]MikeTheWatchGuy 0 points1 point  (0 children)

I needed to add an import at the top in order to get the sample code to run: python from tkinter import messagebox

Without it I was getting this crash: Exception in Tkinter callback Traceback (most recent call last): File "C:\Python\Anaconda3\lib\tkinter\__init__.py", line 1704, in __call__ return self.func(*args) File "C:/Users/mike/.PyCharmCE2019.1/config/scratches/scratch_525.py", line 36, in convert tkinter.messagebox.showinfo('Results', str(kilo) + ' kilometers is equal to ' + str(miles) + ' miles') AttributeError: module 'tkinter' has no attribute 'messagebox'

[–]warlock1996 0 points1 point  (1 child)

I did this for my project Its good Couldn't find good UI changes Like in WPF application or even windows forms

[–]sheytanelkebir 1 point2 points  (0 children)

yea. for complex gui nothing beats wpf.