5 Best Ways to Create a GUI to Get Sunset and Sunrise Times Using Python

πŸ’‘ Problem Formulation: Say you want to design a graphical user interface (GUI) in Python that can fetch and display the sunset and sunrise times for a given location. The input should typically include coordinates or a city name, and the output should show the corresponding times for the natural phenomena. This article solves this by exploring different methods to create such a GUI effectively.

Method 1: Using Tkinter and the requests library

Tkinter is Python’s standard GUI toolkit, allowing for an easy way to create windows and widgets. Alongside the requests library to fetch data from an API, a user can enter their location and receive sunset and sunrise times. A suitable API for this is the Sunrise-Sunset API, which provides the necessary data for free.

Here’s an example:

import tkinter as tk
import requests

def get_times():
    response = requests.get(f"https://api.sunrise-sunset.org/json?lat={lat_entry.get()}&lng={lng_entry.get()}&formatted=0")
    times = response.json()['results']
    sunrise_label.config(text="Sunrise: " + times['sunrise'])
    sunset_label.config(text="Sunset: " + times['sunset'])

root = tk.Tk()

lat_entry = tk.Entry(root)
lat_entry.pack()

lng_entry = tk.Entry(root)
lng_entry.pack()

fetch_button = tk.Button(root, text="Get Times", command=get_times)
fetch_button.pack()

sunrise_label = tk.Label(root, text="Sunrise:")
sunrise_label.pack()

sunset_label = tk.Label(root, text="Sunset:")
sunset_label.pack()

root.mainloop()

Output:

A GUI window with entry fields for latitude and longitude, and labels that will be updated with sunrise and sunset times upon clicking the “Get Times” button.

The provided code snippet sets up a basic Tkinter window with two entry fields for user input of latitude and longitude. When the “Get Times” button is clicked, it makes a request to the Sunrise-Sunset API, extracts the sunset and sunrise times, and updates the labels in the GUI accordingly.

Method 2: Using PySimpleGUI and the urllib library

PySimpleGUI offers a simpler interface for GUI creation with themes that resemble modern apps. It can also be paired with the urllib library for data retrieval from APIs. You still need a working knowledge of how to parse JSON, as you’ll be getting and displaying the sunset and sunrise times from an internet resource.

Here’s an example:

import PySimpleGUI as sg
from urllib.request import urlopen
import json

layout = [
    [sg.Text("Latitude"), sg.InputText()],
    [sg.Text("Longitude"), sg.InputText()],
    [sg.Button("Get Times"), sg.Button("Exit")],
    [sg.Text("", size=(40, 1), key="SUNRISE"), sg.Text("", size=(40, 1), key="SUNSET")]
]

window = sg.Window("Sunrise and Sunset Times", layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == "Exit":
        break
    if event == "Get Times":
        response = urlopen(f"https://api.sunrise-sunset.org/json?lat={values[0]}&lng={values[1]}&formatted=0")
        times = json.load(response)['results']
        window["SUNRISE"].update("Sunrise: " + times['sunrise'])
        window["SUNSET"].update("Sunset: " + times['sunset'])

window.close()

Output:

A PySimpleGUI window with input fields for latitude and longitude and output texts for sunrise and sunset times.

This example script creates a GUI application using PySimpleGUI with inputs for latitude and longitude. Upon clicking “Get Times”, it fetches the times using urllib and updates the text elements with the sunrise and sunset times respectively.

Method 3: Using PyQt5 and the http.client library

PyQt5 is a set of Python bindings for the Qt application framework, offering extensive features for creating complex GUI applications. When paired with Python’s http.client library, you can design a robust application to display sunrise and sunset times.

Here’s an example:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QLineEdit, QLabel
from http.client import HTTPSConnection
import json

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.lat_input = QLineEdit(self)
        self.lng_input = QLineEdit(self)
        self.get_button = QPushButton('Get Times', self)
        self.sunrise_label = QLabel('Sunrise:', self)
        self.sunset_label = QLabel('Sunset:', self)

        vbox = QVBoxLayout()
        vbox.addWidget(self.lat_input)
        vbox.addWidget(self.lng_input)
        vbox.addWidget(self.get_button)
        vbox.addWidget(self.sunrise_label)
        vbox.addWidget(self.sunset_label)

        self.get_button.clicked.connect(self.on_click)

        self.setLayout(vbox)
        self.setWindowTitle('Sunrise and Sunset Times')
        self.show()

    def on_click(self):
        conn = HTTPSConnection("api.sunrise-sunset.org")
        conn.request("GET", f"/json?lat={self.lat_input.text()}&lng={self.lng_input.text()}&formatted=0")
        response = conn.getresponse()
        times = json.loads(response.read())['results']
        self.sunrise_label.setText(f"Sunrise: {times['sunrise']}")
        self.sunset_label.setText(f"Sunset: {times['sunset']}")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Window()
    sys.exit(app.exec_())

Output:

A PyQt5 application window with QLineEdit widgets for user input, and QLabel widgets displaying the fetched sunrise and sunset times.

In this PyQt5 example, a class-based structure is used to create a windowed application with input fields and labels. A button press triggers a request using the http.client library; it then reads and decodes the response to update the GUI.

Method 4: Using Kivy and asynchronous requests with aiohttp

Kivy is an open-source Python library for developing multitouch applications. It is cross-platform (Linux/OS X/Windows/Android/iOS) and released under the MIT license. With Kivy, you can cater to users on multiple platforms. We can use aiohttp for making asynchronous HTTP requests to an API, reducing the application’s response time by not blocking the main thread.

Here’s an example:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.label import Label
import aiohttp
import asyncio

class SunriseSunsetApp(App):
    async def fetch_times(self, lat, lng):
        async with aiohttp.ClientSession() as session:
            async with session.get(f"https://api.sunrise-sunset.org/json?lat={lat}&lng={lng}&formatted=0") as response:
                times = await response.json()
                return times['results']

    def build(self):
        self.lat_input = TextInput(text="Latitude")
        self.lng_input = TextInput(text="Longitude")
        self.get_button = Button(text="Get Times")
        self.sunrise_label = Label(text="Sunrise:")
        self.sunset_label = Label(text="Sunset:")

        layout = BoxLayout(orientation='vertical')
        layout.add_widget(self.lat_input)
        layout.add_widget(self.lng_input)
        layout.add_widget(self.get_button)
        layout.add_widget(self.sunrise_label)
        layout.add_widget(self.sunset_label)

        self.get_button.bind(on_press=self.on_button_press)

        return layout

    def on_button_press(self, instance):
        asyncio.ensure_future(self.update_labels())

    async def update_labels(self):
        times = await self.fetch_times(self.lat_input.text, self.lng_input.text)
        self.sunrise_label.text = f"Sunrise: {times['sunrise']}"
        self.sunset_label.text = f"Sunset: {times['sunset']}"

if __name__ == "__main__":
    SunriseSunsetApp().run()

Output:

A Kivy application with text input boxes and asynchronous updates to labels for sunrise and sunset times.

This method uses the Kivy framework for creating the GUI and the aiohttp library for asynchronous web requests, which is helpful for not interrupting user interaction while waiting for a response.

Bonus One-Liner Method 5: Using eel with a Web Front-End

Eel is a little Python library for making simple Electron-like HTML/JS GUI apps, with full access to Python capabilities. It leverages the Chrome browser for rendering the frontend.

Here’s an example:

import eel

eel.init('web')
eel.start('main.html', size=(300, 200))

# In main.html
# 
# 
# 
# 
#   eel.expose(getTimes);
#   async function getTimes() {
#       let response = await fetch(`https://api.sunrise-sunset.org/json?lat=${document.getElementById('lat').value}&lng=${document.getElementById('lng').value}&formatted=0`);
#       let data = await response.json();
#       alert(`Sunrise: ${data.results.sunrise}, Sunset: ${data.results.sunset}`);
#   }
# 

Output:

A simple web-based GUI created using HTML and JavaScript, which displays a popup with the sunrise and sunset times after fetching.

This code snippet starts an app with eel, and the frontend logic is written in HTML/JS where an alert displays the times. It’s an efficient way to use web technologies you might already be familiar with to create a desktop application.

Summary/Discussion

  • Method 1: Tkinter and requests. Strengths: Uses standard libraries, no additional installs required. Weaknesses: Less modern-looking UI, synchronous blocking I/O requests.
  • Method 2: PySimpleGUI and urllib. Strengths: Easier to write and understand, more modern UI. Weaknesses: Requires additional library installation, still uses blocking I/O.
  • Method 3: PyQt5 and http.client. Strengths: Highly customizable and powerful UI, great for complex applications. Weaknesses: Steeper learning curve, blocking I/O.
  • Method 4: Kivy and aiohttp. Strengths: Cross-platform support, asynchronous for non-blocking I/O. Weaknesses: Asynchronous programming can be complex, requires additional libraries.
  • Bonus One-Liner Method 5: Eel with a web front-end. Strengths: Simple and fast to develop, allows usage of web technologies. Weaknesses: Less control over UI, depends on the Chrome browser being installed.