|
| 1 | +# Build Your First Desktop Application with Electron |
| 2 | +Chen Meng </br> |
| 3 | +May 19, 2020 |
| 4 | + |
| 5 | +**Objective:** |
| 6 | +This guide introduces Electron and will help you develop your first Electron application. |
| 7 | + |
| 8 | +**Audience:** |
| 9 | +This guide targets people interested in Electron but have little to no experience with it. It is recommended that readers have some experience in html, css and javascript since knowing them is very essential to build an Electron application. |
| 10 | + |
| 11 | +## What is Electron? |
| 12 | +Electron is a framework for creating cross-platform desktop applications with web programming languages like html, css, and javascript. By cross-platform, it means that you can build and deploy your application on all major operating systems(OS) including Windows, Linux, and MacOS with the same source code. The reason why you don’t have to adapt your program to different operating systems is that Electron runs your code in a Chromium environment independent of your OS. So, let’s jump into our first Electron app! |
| 13 | + |
| 14 | +## Get Started: Hello World Application! |
| 15 | +Of course, the easiest and simplest way to learn a new technology is to create a hello world project of your own, so we are going to build one. |
| 16 | + |
| 17 | +### Prerequisite: Installation and Setup |
| 18 | +Before diving into our hello world application, make sure you have node.js installed on your computer. node.js is a javascript runtime environment that can execute javascript code outside of a web browser, and Electron also uses it to run your javascript code. |
| 19 | + |
| 20 | +An Electron application is essentially a node.js application, so the first step is to create a node project. Open your command line client and create a new folder to store your project, and in that folder, run: |
| 21 | + |
| 22 | +``` |
| 23 | +npm init |
| 24 | +``` |
| 25 | + |
| 26 | +npm will guide you to create a basic package.json file, in the end it might look like this: |
| 27 | +```javascript |
| 28 | +{ |
| 29 | + "name": "Hello World", |
| 30 | + "version": "1.0.0", |
| 31 | + "main": "main.js", |
| 32 | + "scripts": { |
| 33 | + "test": "echo \"Error: no test specified\" && exit 1" |
| 34 | + }, |
| 35 | + "author": "your-name", |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +Make sure you remember the main field, since it directs to the file being executed when the program starts. In this case, the main field directs to file main.js. |
| 40 | + |
| 41 | +Next, we need to add a start script as instruction for Electron to execute current package: |
| 42 | +```javascript |
| 43 | +{ |
| 44 | + "name": "Hello World", |
| 45 | + "version": "1.0.0", |
| 46 | + "main": "main.js", |
| 47 | + "scripts": { |
| 48 | + "start": "electron ." |
| 49 | + }, |
| 50 | + "author": "my-name", |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +With package.json configured, we have to install Electron into our project. It is recommended to install it as a development dependency: |
| 55 | +``` |
| 56 | +npm install --save-dev electron |
| 57 | +``` |
| 58 | + |
| 59 | +### Writing Our Hello World App |
| 60 | +First let’s look into main.js, the entry portal into our hello world application. For Electron, all of its APIs and features can be accessed via the electron module by using the require() function, just like every node module: |
| 61 | +```javascript |
| 62 | +const electron = require('electron') |
| 63 | +``` |
| 64 | + |
| 65 | +The require function stores all of Electron’s features into the variable electron as namespaces, and each feature can be accessed via calling electron.feature_name. For every application, its life cycle is managed through electron.app. A window can be created using the electron.BrowserWindow class. We can access the features by calling: |
| 66 | +```javascript |
| 67 | +const app = electron.app; |
| 68 | +const BrowserWindow = electron.BrowserWindow; |
| 69 | +``` |
| 70 | + |
| 71 | +Or alternatively: |
| 72 | +```javascript |
| 73 | +const { app, BrowserWindow } = require('electron'); |
| 74 | +``` |
| 75 | + |
| 76 | +For our hello world application, a simple main.js file can wait for app to be ready and then open a BrowserWindow, which then loads an html file as the main UI: |
| 77 | +```javascript |
| 78 | +const { app, BrowserWindow } = require('electron'); |
| 79 | +function createWindow() { |
| 80 | + // Create the browser window. |
| 81 | + win = new BrowserWindow({ |
| 82 | + // Set options for the window |
| 83 | + width: 800, |
| 84 | + height: 600, |
| 85 | + webPreferences: { |
| 86 | + nodeIntegration: true |
| 87 | + } |
| 88 | + }) |
| 89 | + // BrowserWindow will load index.html upon creation |
| 90 | + win.loadFile('index.html') |
| 91 | +} |
| 92 | +// BrowserWindow is created when app is ready |
| 93 | +app.whenReady().then(createWindow) |
| 94 | +``` |
| 95 | + |
| 96 | +Finally, we write a simple index.html to display our hello world page: |
| 97 | +```html |
| 98 | +<html> |
| 99 | + <head> |
| 100 | + <meta charset="UTF-8"> |
| 101 | + <title>Hello World!</title> |
| 102 | + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" /> |
| 103 | + </head> |
| 104 | + <body> |
| 105 | + <h1>Hello Electron and hello world!</h1> |
| 106 | + </body> |
| 107 | +</html> |
| 108 | +``` |
| 109 | +### Running Your Application |
| 110 | +After finishing our hello world project, it’s time to run it! To run, simply type this command. It will execute the “electron .” command we have set in package.json. |
| 111 | +``` |
| 112 | +npm start |
| 113 | +``` |
| 114 | +</br> |
| 115 | +A window will show up in your computer: </br> |
| 116 | + |
| 117 | + |
| 118 | +Watching the window show up is very exciting! yet … a bit boring. So, why not create a more interesting program? |
| 119 | + |
| 120 | +## What Electron Can Do: Build A More Complicated Application |
| 121 | + |
| 122 | +For a more complicated application, we are going to build a small timer widget that lives on the top corner of the screen. The source code can be found in this Github repo. |
| 123 | + |
| 124 | +### Step1: Start With the UI |
| 125 | + |
| 126 | +First, let’s build a basic UI for the timer in index.html. It should have two input fields, one for minutes and the other for seconds. It should also have two buttons to start and stop the timer, and a text field to display the timer: |
| 127 | +```html |
| 128 | +<body> |
| 129 | + <div class="container"> |
| 130 | + <ul> <!-- Input fields--> |
| 131 | + <li> <input type="text" id="minutes" value="0"> </li> |
| 132 | + <li> minutes</li> |
| 133 | + <li> <input type="text" id="seconds" value="0"> </li> |
| 134 | + <li> seconds</li> |
| 135 | + </ul> |
| 136 | + <ul> <!-- Buttons --> |
| 137 | + <li> <button id="startBtn"> start </button> </li> |
| 138 | + <li> <button id="stopBtn" style="margin-left: 25px"> |
| 139 | + stop </button> </li> |
| 140 | + </ul> |
| 141 | + <!-- Display field --> |
| 142 | + <p id="display">00:00</p> |
| 143 | + </div> |
| 144 | + <!-- Link to the body of the timer --> |
| 145 | + <script> require('./timer.js') </script> |
| 146 | +</body> |
| 147 | +``` |
| 148 | + |
| 149 | +Then, we can add some styles to the fields and buttons to rearrange them. This is a very basic UI, feel free to make it look nicer: |
| 150 | +```css |
| 151 | +ul{ padding-left: 0px; } |
| 152 | +li { display: inline; } |
| 153 | +input { width: 50px; } |
| 154 | +button { width: 80px; } |
| 155 | +#display{ |
| 156 | + font-size: 50px; |
| 157 | + margin-top: 20px; |
| 158 | + margin-bottom: 20px; |
| 159 | + margin-left: 40px; |
| 160 | +} |
| 161 | +.container{ width: 300px; } |
| 162 | +``` |
| 163 | + |
| 164 | +### Step2: Implement the Body of the Timer |
| 165 | +The next step is to implement the body of the timer in timer.js, which contains the button listeners to start and stop the timer. It also has the timer function which counts down and update the UI accordingly: |
| 166 | + |
| 167 | +```javascript |
| 168 | +// dialog is used to show message box in the app |
| 169 | +const { dialog } = require('electron').remote; |
| 170 | +// Input fields and display fields |
| 171 | +var minutesField = document.getElementById('minutes'); |
| 172 | +var secondsField = document.getElementById('seconds'); |
| 173 | +var display = document.getElementById('display'); |
| 174 | +var myTimer; // Stores the timer used to count time |
| 175 | + |
| 176 | +// Start Button |
| 177 | +const startBtn = document.getElementById('startBtn'); |
| 178 | +startBtn.addEventListener('click', function(){ |
| 179 | + minutes = parseInt(minutesField.value, 10); |
| 180 | + seconds = parseInt(secondsField.value, 10); |
| 181 | + // Check for valid inputs, if not valid then timer won't start |
| 182 | + if(minutes >= 0 && minutes <= 59 && seconds >=0 && seconds <=59){ |
| 183 | + minutesField.disabled = true; |
| 184 | + secondsField.disabled = true; |
| 185 | + startBtn.disabled = true; |
| 186 | + stopBtn.disabled = false; |
| 187 | + var timer = minutes*60 + seconds; |
| 188 | + // Start timer |
| 189 | + myTimer = startTimer(timer, display); |
| 190 | + } |
| 191 | +}); |
| 192 | +const stopBtn = document.getElementById('stopBtn'); |
| 193 | +// Disabled at first |
| 194 | +stopBtn.disabled = true; |
| 195 | +stopBtn.addEventListener('click', function(){ |
| 196 | + clearInterval(myTimer); |
| 197 | + clearTimer(); |
| 198 | +}); |
| 199 | +// Function to start the timer |
| 200 | +function startTimer(time, display) { |
| 201 | + const timer = setInterval(function () { |
| 202 | + minutes = Math.floor(time/60); |
| 203 | + seconds = time%60; |
| 204 | + minutes = minutes < 10 ? "0" + minutes : minutes; |
| 205 | + seconds = seconds < 10 ? "0" + seconds : seconds; |
| 206 | + |
| 207 | + display.textContent = minutes + ":" + seconds; |
| 208 | + // Time's up when time == -1 |
| 209 | + if (--time < 0) { |
| 210 | + dialog.showMessageBox({ |
| 211 | + title: "Time's Up!", |
| 212 | + message: "Buzzzzzzz, time's up!" |
| 213 | + }); |
| 214 | + clearTimer(); |
| 215 | + clearInterval(timer); |
| 216 | + } |
| 217 | + }, 1000); //set the interval to 1000ms (1s), function body is executed once per second |
| 218 | + return timer; |
| 219 | +} |
| 220 | + |
| 221 | +//Resets the fields and buttons |
| 222 | +function clearTimer(){ |
| 223 | + display.textContent = "00:00"; |
| 224 | + minutesField.value = "0"; |
| 225 | + secondsField.value = "0"; |
| 226 | + startBtn.disabled = false; |
| 227 | + stopBtn.disabled = true; |
| 228 | + minutesField.disabled = false; |
| 229 | + secondsField.disabled = false; |
| 230 | +} |
| 231 | +``` |
| 232 | + |
| 233 | +### Step3: Configure the Electron Window |
| 234 | +The last step is to configure main.js, the entry portal of the program: |
| 235 | + |
| 236 | +```javascript |
| 237 | +const { app, BrowserWindow } = require('electron') |
| 238 | + |
| 239 | +function createWindow() { |
| 240 | + // Create the browser window. |
| 241 | + win = new BrowserWindow({ |
| 242 | + // Dimension of the window |
| 243 | + width: 230, |
| 244 | + height: 170, |
| 245 | + // Starting position of the window on screen: topleft |
| 246 | + x: 0, |
| 247 | + y: 0, |
| 248 | + // Window is not resizable, minimizable, or maximizable |
| 249 | + resizable: false, |
| 250 | + minimizable: false, |
| 251 | + maximizable: false, |
| 252 | + webPreferences: { |
| 253 | + nodeIntegration: true |
| 254 | + } |
| 255 | + }) |
| 256 | + // Load index.html upon creation |
| 257 | + win.loadFile('index.html') |
| 258 | +} |
| 259 | +app.whenReady().then(createWindow) |
| 260 | +``` |
| 261 | + |
| 262 | +With index.html, timer.js, and main.js ready, our timer app is good to go! Let’s run it and see how it behaves. |
| 263 | + |
| 264 | +Step 4: Play With It |
| 265 | +By running npm start, this window should pop up on the top left corner on your screen. It has two text input fields for entering desired minutes and seconds. </br> |
| 266 | + </br> |
| 267 | +We can set a countdown for 1 minute and 5 seconds, then press the start button. The countdown begins. |
| 268 | + </br> |
| 269 | +After counting down to 0, the alert message shows up and the timer is reset. Our timer widget seems to work well! |
| 270 | + |
| 271 | + |
| 272 | +## Conclusion |
| 273 | + |
| 274 | +This guide should have given you an overview of how to build a simple cross-platform desktop application with Electron. If you have trouble following this guide, I suggest learning more about node.js before moving forward. Happy hacking! |
| 275 | + |
| 276 | +Relevant Resources: </br> |
| 277 | +Electron Official Beginner's Guide: https://www.electronjs.org/docs/tutorial/first-app </br> |
| 278 | +Electron Official Documentation: https://www.electronjs.org/docs </br> |
| 279 | +Electron APIs: https://www.electronjs.org/docs/api </br> |
| 280 | +Node.js Introduction: https://nodejs.dev/learn </br> |
0 commit comments