├── .gitignore ├── README.md ├── engine ├── .DS_Store ├── boot.sh ├── object_detection.py └── weather_engine.py ├── gui ├── .DS_Store ├── gui.html ├── images │ ├── Unknown-1.png │ ├── face.jpeg │ ├── recognition.png │ └── weather-icon.png ├── linkers │ └── weather.js ├── object.html └── weather.html ├── main.js ├── package.json ├── renderer.js ├── requirements.txt └── samples ├── 1.png └── 3.png /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # electron 4 | /angular-electron-win32-x64 5 | Release.key 6 | *.zip 7 | 8 | # compiled output 9 | /tmp 10 | /out-tsc 11 | 12 | # dependencies 13 | /node_modules 14 | /stuff 15 | 16 | # IDEs and editors 17 | /.idea 18 | .project 19 | .classpath 20 | .c9/ 21 | *.launch 22 | .settings/ 23 | *.sublime-workspace 24 | 25 | # IDE - VSCode 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | 32 | # misc 33 | /.sass-cache 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | npm-debug.log 38 | testem.log 39 | /typings 40 | 41 | # e2e 42 | /e2e/*.js 43 | /e2e/*.map 44 | 45 | # System Files 46 | .DS_Store 47 | Thumbs.db 48 | 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python-app-with-electron-gui 2 | A better way to make GUIs for your Python apps 3 | 4 | ![visitors](https://visitor-badge.glitch.me/badge?page_id=SouravJohar.visitor-badge) 5 | 6 | Use HTML, JavaScript and CSS to make highly customized, cross platfrom desktop apps which use native Python backends. 7 | 8 | https://youtu.be/627VBkAhKTc 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Note: This is for educational purposes only, this may not be efficient or bug-free. Also, this is just a demo on how 17 | JS and Python can be used to interact together. This demo is *NOT* meant to show face detection or object detection. 18 | 19 | ## General Dependenices 20 | * Python 21 | * NodeJS 22 | * electron.js 23 | * python-shell 24 | 25 | ## Specific Dependencies 26 | * weather module: 27 | * requests 28 | * beautifulsoup4 29 | 30 | * object detection module 31 | * Flask 32 | * tensorflow 33 | * keras 34 | 35 | ## Usage 36 | * Clone the repo, and then 37 | ```sh 38 | $ cd electron-app-with-python-gui 39 | $ pip install -r requirements.txt 40 | $ npm install 41 | $ npm start 42 | ``` 43 | * If you want to use the object detection module, make sure the flask server [object_detection.py] is up and running before starting the GUI. 44 | ```sh 45 | $ cd engine 46 | $ python object_detection.py 47 | ``` 48 | 49 | ## Note: 50 | 51 | weather_engine.py uses web-scraping to pull data off the internet, from a particular website. If this site happens to be modified 52 | or changed in the future, the code *might* break. However, this can be fixed by analyzing the new layout of the site and adjusting 53 | the python code accordingly. 54 | -------------------------------------------------------------------------------- /engine/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouravJohar/python-app-with-electron-gui/99e2eb130ba66a5dbb1b139feba9f06edb385372/engine/.DS_Store -------------------------------------------------------------------------------- /engine/boot.sh: -------------------------------------------------------------------------------- 1 | kill -9 $(lsof -t -i:5000) 2 | echo killed pre 3 | python object_detection.py & 4 | cd .. 5 | cd gui 6 | npm start 7 | kill -9 $(lsof -t -i:5000) 8 | echo killed 9 | -------------------------------------------------------------------------------- /engine/object_detection.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request 2 | from keras.applications.inception_v3 import * 3 | from keras.preprocessing import image 4 | import tensorflow as tf 5 | import numpy as np 6 | import os 7 | import json 8 | 9 | app = Flask(__name__, template_folder=os.path.abspath("../gui/")) 10 | 11 | model = InceptionV3(weights='imagenet') 12 | graph = tf.get_default_graph() 13 | 14 | 15 | def predict(path): 16 | img = image.load_img(path, target_size=(299, 299)) 17 | xy = image.img_to_array(img) 18 | xy = np.expand_dims(xy, axis=0) 19 | xy = preprocess_input(xy) 20 | global graph 21 | with graph.as_default(): 22 | preds = model.predict(xy) 23 | preds = decode_predictions(preds, top=3)[0] 24 | acc = [] 25 | classes = [] 26 | for x in preds: 27 | acc.append(x[2]) 28 | classes.append(x[1]) 29 | return acc, classes 30 | 31 | 32 | @app.route("/detect", methods=["GET", "POST"]) 33 | def detect(): 34 | if request.method == "GET": 35 | return render_template("object.html") 36 | 37 | if request.method == "POST": 38 | path = request.form["path"] 39 | 40 | accuracies, classes = predict(path) 41 | 42 | return render_template("object.html", preds=accuracies, 43 | classes=json.dumps(classes), img=path) 44 | 45 | app.run() 46 | -------------------------------------------------------------------------------- /engine/weather_engine.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup as bs 3 | import sys 4 | 5 | city = sys.argv[1] 6 | 7 | 8 | def get_weather(place): 9 | place = place.replace(" ", "-") 10 | url = "https://www.weather-forecast.com/locations/" + place + "/forecasts/latest" 11 | r = requests.get(url) 12 | soup = bs(r.content, "lxml") 13 | weather = soup.findAll("span", {"class": "phrase"})[0].text 14 | return weather 15 | 16 | print(get_weather(city)) 17 | sys.stdout.flush() 18 | -------------------------------------------------------------------------------- /gui/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouravJohar/python-app-with-electron-gui/99e2eb130ba66a5dbb1b139feba9f06edb385372/gui/.DS_Store -------------------------------------------------------------------------------- /gui/gui.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 |

Powered by Python

9 |

Rendered by HTML and JavaScript

10 |
11 |
12 |
13 |
14 | 15 |
16 | 17 |
18 |
19 |
20 |
21 | 22 |
23 | 24 |
25 |
26 |
27 | 28 | -------------------------------------------------------------------------------- /gui/images/Unknown-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouravJohar/python-app-with-electron-gui/99e2eb130ba66a5dbb1b139feba9f06edb385372/gui/images/Unknown-1.png -------------------------------------------------------------------------------- /gui/images/face.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouravJohar/python-app-with-electron-gui/99e2eb130ba66a5dbb1b139feba9f06edb385372/gui/images/face.jpeg -------------------------------------------------------------------------------- /gui/images/recognition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouravJohar/python-app-with-electron-gui/99e2eb130ba66a5dbb1b139feba9f06edb385372/gui/images/recognition.png -------------------------------------------------------------------------------- /gui/images/weather-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouravJohar/python-app-with-electron-gui/99e2eb130ba66a5dbb1b139feba9f06edb385372/gui/images/weather-icon.png -------------------------------------------------------------------------------- /gui/linkers/weather.js: -------------------------------------------------------------------------------- 1 | let {PythonShell} = require('python-shell') 2 | var path = require("path") 3 | 4 | 5 | function get_weather() { 6 | 7 | var city = document.getElementById("city").value 8 | 9 | var options = { 10 | scriptPath : path.join(__dirname, '/../engine/'), 11 | args : [city] 12 | } 13 | 14 | let pyshell = new PythonShell('weather_engine.py', options); 15 | 16 | 17 | pyshell.on('message', function(message) { 18 | swal(message); 19 | }) 20 | document.getElementById("city").value = ""; 21 | } 22 | -------------------------------------------------------------------------------- /gui/object.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 14 | 27 | 28 | 29 | 58 | 59 |
60 |
61 |
62 |

Object detection

63 |

Powered by Python

64 |

Rendered by HTML and JavaScript

65 |
66 |
67 | 68 |
69 | 70 |

71 |
72 | 73 | 74 |
75 | 76 | {% if preds %} 77 |
78 | 81 | 82 | {% endif %} 83 |
84 |
85 | 86 | -------------------------------------------------------------------------------- /gui/weather.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 | 11 | 12 |
13 |

Weather Forecast

14 |

Powered by Python

15 |

Rendered by HTML and JavaScript

16 |
17 |
18 | 19 | 20 | 21 | 22 |
23 | 24 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron') 2 | // Module to control application life. 3 | const app = electron.app 4 | // Module to create native browser window. 5 | const BrowserWindow = electron.BrowserWindow 6 | 7 | const path = require('path') 8 | const url = require('url') 9 | 10 | // Keep a global reference of the window object, if you don't, the window will 11 | // be closed automatically when the JavaScript object is garbage collected. 12 | let mainWindow 13 | 14 | function createWindow () { 15 | // Create the browser window. 16 | mainWindow = new BrowserWindow({width: 800, height: 600}) 17 | 18 | // and load the index.html of the app. 19 | mainWindow.loadURL(url.format({ 20 | pathname: path.join(__dirname, '/gui/gui.html'), 21 | protocol: 'file:', 22 | slashes: true 23 | })) 24 | 25 | // Open the DevTools. 26 | // mainWindow.webContents.openDevTools() 27 | 28 | // Emitted when the window is closed. 29 | mainWindow.on('closed', function () { 30 | // Dereference the window object, usually you would store windows 31 | // in an array if your app supports multi windows, this is the time 32 | // when you should delete the corresponding element. 33 | mainWindow = null 34 | }) 35 | } 36 | 37 | // This method will be called when Electron has finished 38 | // initialization and is ready to create browser windows. 39 | // Some APIs can only be used after this event occurs. 40 | app.on('ready', createWindow) 41 | 42 | // Quit when all windows are closed. 43 | app.on('window-all-closed', function () { 44 | // On OS X it is common for applications and their menu bar 45 | // to stay active until the user quits explicitly with Cmd + Q 46 | 47 | app.quit() 48 | }) 49 | 50 | app.on('activate', function () { 51 | // On OS X it's common to re-create a window in the app when the 52 | // dock icon is clicked and there are no other windows open. 53 | if (mainWindow === null) { 54 | createWindow() 55 | } 56 | }) 57 | 58 | // In this file you can include the rest of your app's specific main process 59 | // code. You can also put them in separate files and require them here. 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "python-app-with-electron-gui", 3 | "version": "1.0.0", 4 | "description": "A minimal Electron application", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "electron ." 8 | }, 9 | "license": "CC0-1.0", 10 | "devDependencies": { 11 | "electron": "^1.8.4" 12 | }, 13 | "dependencies": { 14 | "python-shell": "^1.0.7" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /renderer.js: -------------------------------------------------------------------------------- 1 | // This file is required by the index.html file and will 2 | // be executed in the renderer process for that window. 3 | // All of the Node.js APIs are available in this process. 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | beautifulsoup4 3 | Flask 4 | numpy 5 | keras 6 | tensorflow 7 | lxml 8 | -------------------------------------------------------------------------------- /samples/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouravJohar/python-app-with-electron-gui/99e2eb130ba66a5dbb1b139feba9f06edb385372/samples/1.png -------------------------------------------------------------------------------- /samples/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SouravJohar/python-app-with-electron-gui/99e2eb130ba66a5dbb1b139feba9f06edb385372/samples/3.png --------------------------------------------------------------------------------