Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.


    To learn more about how to use our BBCode feature, please click here.

    Thank you, Code Forum.

Version 2 of my weather app.

menator01

Gold Coder
This version should work world wide. May have some bugs when it comes to the wind direction arrow. I've tried testing it and the rain.
To try it create a virtual environment and use pip to run the requirements.txt to install needed modules.
You can download the zip file from my-python to get the images or create your own.

data.py
Python:
import openmeteo_requests
import requests_cache
from retry_requests import retry
from datetime import datetime
import json
import requests
class Data:
    ''' Class makes the calls for data and does some formatting '''
    def __init__(self):
        # Setup the Open-Meteo API client with cache and retry on error
        cache_session = requests_cache.CachedSession('.cache', expire_after = 3600)
        retry_session = retry(cache_session, retries = 5, backoff_factor = 0.2)
        openmeteo = openmeteo_requests.Client(session = retry_session)
        location = json.loads(requests.get('http://ipinfo.io/json').text)   
        info = {
            'country': location.get('country'),
            'region': location.get('region'),
            'city': location.get('city'),
            'latitude': location.get('loc').split(',')[0],
            'longitude': location.get('loc').split(',')[1]
        }
        # Make sure all required weather variables are listed here
        # The order of variables in hourly or daily is important to assign them correctly below
        url = "https://api.open-meteo.com/v1/forecast"
        params = {
            "latitude": info['latitude'],
            "longitude": info['longitude'],
            "current": ["temperature_2m", "relative_humidity_2m", "apparent_temperature", "precipitation", "cloud_cover",
                        "wind_speed_10m", "wind_direction_10m", "wind_gusts_10m"],
            "temperature_unit": "fahrenheit",
            "wind_speed_unit": "mph",
            "precipitation_unit": "inch",
            "timeformat": "unixtime"
        }
        responses = openmeteo.weather_api(url, params=params)
        response = responses[0]
        current = response.Current()
        # Create dict and set wind directions
        winddirect = {}
        winddirect['N'] = [0,360]
        winddirect['NNE'] = [n for n in range(1,45)]
        winddirect['NE'] = [45]
        winddirect['ENE'] = [n for n in range(46,90)]
        winddirect['E'] = [90]
        winddirect['ESE'] = [n for n in range(91,135)]
        winddirect['SE'] = [135]
        winddirect['SSE'] = [n for n in range(136,180)]
        winddirect['S'] = [180]
        winddirect['SSW'] = [n for n in range(181,225)]
        winddirect['SW'] = [225]
        winddirect['WSW'] = [n for n in range(226,270)]
        winddirect['W'] = [270]
        winddirect['WNW'] = [n for n in range(271,315)]
        winddirect['NW'] = [315]
        winddirect['NNW'] = [n for n in range(316,360)]
        # Some variables for testing conditions
        self.direct = round(current.Variables(6).Value())
        precip = round(current.Variables(3).Value())
        cloudy = round(current.Variables(4).Value())
       
        # This loop sets text for wind direction
        for key, value in winddirect.items():
            if round(current.Variables(6).Value()) in value:
                direct = key
       
        # Dict for holding cloudy conditions
        cloud = {}
        cloud['clear skies'] = [n for n in range(0,5)]
        cloud['partly cloudy'] = [n for n in range(5,51)]
        cloud['mostly cloudy'] = [n for n in range(51, 86)]
        cloud['cloudy'] = [n for n in range(86,101)]
        # Compairing cloud dict with retreived data
        for key, value in cloud.items():
            if cloudy in value:
                option = key
       
        # Create dict for testing on image to show
        faze = {}
        faze['day'] = {
            'clear skies':'sunny.png',
            'partly cloudy':'day_cloudy.png',
            'mostly cloudy': 'day_cloudy.png',
            'cloudy': 'cloudy.png',
            'rain': 'rain.png'
        }
        faze['night'] = {
            'clear skies': 'moonlight.png',
            'partly cloudy':'night_cloudy.png',
            'mostly cloudy': 'night_cloudy.png',
            'cloudy': 'cloudy.png',
            'rain':'rain.png'
        }
        # Get the hour for testing if it's day or night
        # Broke it down to 12 hour periods 1am 6pm is day
        hour = datetime.now().strftime('%H')
        if hour >= '01' and hour <= '18':
            for key, value in faze['day'].items():
                if key == option:
                    img = faze['day'][key]
                if precip > 0:
                    option = '   rain'
                    img = faze['day']['rain']
        else:
            for key, value in faze['night'].items():
                if key == option:
                    img = faze['night'][option]
                if precip > 0:
                    img = faze['night']['rain']
                    option = '   rain'
       
        # Create dict and set key value pairs
        self.weather = {}
        self.weather['location'] = ', '.join([info['country'], info['city'], info['region']])
        self.weather['Date'] = datetime.now().strftime('%A %B %d, %Y')
        self.weather['Time'] = datetime.now().strftime('%I:%M:%S %p')
        self.weather['temp'] = f'{round(current.Variables(0).Value())}°F'
        self.weather['humidity'] = f'{round(current.Variables(1).Value())}%'
        self.weather['feels like'] = f'{round(current.Variables(2).Value())}°F'
        self.weather['precipitation'] = f'{round(current.Variables(3).Value())}%'
        self.weather['cloud cover'] = f'{round(current.Variables(4).Value())}%'
        self.weather['wind speed'] = f'{round(current.Variables(5).Value())} mph'
        self.weather['wind direction'] = direct
        self.weather['wind gust'] = f'{round(current.Variables(7).Value())} mph'
        self.weather['image'] = (option, img)

weather.py
Python:
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout, QHBoxLayout,
                                QVBoxLayout,QLabel, QFrame, QGraphicsScene, QGraphicsView)
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QPixmap, QImage, QIcon, QTransform
from datetime import datetime
from data import Data
class Arrow:
    ''' Class creates the wind direction arrow '''
    def __init__(self):
        ''' Set up Graphics screen and view '''
        pixmap = QPixmap('images/arrow.png')
        self.pixmap = pixmap.scaled(pixmap.width()/1.25, pixmap.height()/1.25)
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.view.setFrameStyle(0)
        self.view.setFixedHeight(20)
        self.view.setStyleSheet('padding-right: 50px; margin-left:-20px')
       
    def viewarrow(self, direction=0, text=''):
        self.item = self.scene.addPixmap(self.pixmap)
        # Rotates the arrow
        self.item.setRotation(direction)
        self.item.setTransformOriginPoint(
            self.item.boundingRect().center())
        self.item.setTransformationMode(Qt.SmoothTransformation)
       
        return self.view

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        # image icon from https://www.flaticon.com
        pixmap = QPixmap('images/weather.png')
        appicon = QIcon(pixmap)
        self.setWindowIcon(appicon)
        self.setWindowTitle('Weather App')
        self.setFixedSize(400,450)
        # Create main container
        container = QVBoxLayout()
        widget = QWidget()
        widget.setLayout(container)
        self.setCentralWidget(widget)
        self.show()
        # Create the header
        header = QLabel('PySide6 Weather')
        header.setStyleSheet('background-color: #ffa500; color: #ffffff; font-size: 30px; \
                            font-weight: bold; font-family: cursive; padding: 10px;')
        header.setAlignment(Qt.AlignmentFlag.AlignCenter)
        # Add header to container
        container.addWidget(header)
        # Create content container
        self.content = QGridLayout()
        self.content.setSpacing(10)
        frame = QFrame()
        frame.setLayout(self.content)
        frame.setFrameStyle(QFrame.StyledPanel | QFrame.Plain)       
        # Add content container to main container
        container.addWidget(frame)
        labels = ['location', 'date','time', 'temperature', 'humidity',
            'feels like', 'precipitation', 'cloud cover',
            'wind speed', 'wind direction', 'wind gust']
        self.labels = []
        for index, item in enumerate(labels):
            label = QLabel(f'{item.title()}:')
            label.setStyleSheet('font-weight:500; font-size: 16px;')
            self.content.addWidget(label, index,0,1,1)
            # self.content.addWidget(QLabel(), index, 1,1,1)
        for index, item in enumerate(labels):
            self.labels.append(QLabel())
            self.labels[index].setStyleSheet('font-size: 16px;')
            self.content.addWidget(self.labels[index], index, 1,1,1, Qt.AlignmentFlag.AlignLeft)
            self.content.addWidget(QLabel(), index, 2,1,1)

        # Setup an image label
        self.img_label = QLabel()
        self.img_label.setStyleSheet('padding-left: 80px;')
        self.content.addWidget(self.img_label, 3,1,9,1, Qt.AlignmentFlag.AlignTop)
        # Setup image text label
        self.img_text = QLabel()
        self.img_text.setStyleSheet('margin-left:40px;')
        self.content.addWidget(self.img_text, 8,1,1,1, Qt.AlignmentFlag.AlignCenter)
        # Create container for footer
        footerframe = QGridLayout()
        footerframe.setSpacing(0)
       
        # Add footer container to main container
        container.addLayout(footerframe)
        # Create the logo image
        img = QPixmap('images/my-python-logo.png')
        img = img.scaled(40,20)
        # Add image to label
        logo = QLabel()
        logo.setAlignment(Qt.AlignmentFlag.AlignCenter)
        logo.setStyleSheet('background-color: #ffa500;padding:5px; margin-left: -5.5em;')
        logo.setPixmap(img)
        # Create logo text
        label = QLabel('™ my-python©')
        label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        label.setStyleSheet('padding:5px;margin-left: 3em; font-size: 18px;')
        # Add logo image and text to footer container
        footerframe.addWidget(logo, 0,1,1,1)
        footerframe.addWidget(label,0,1,1,1)

class Controller:
    def __init__(self, window, arrow):
        self.window = window
        self.arrow = arrow
        self.update()
        # Create a timer to update contents
        self.timer = QTimer()
        self.timer.setInterval(300000)
        self.timer.timeout.connect(self.update)
        self.timer.start()
        self.clock_timer = QTimer()
        self.clock_timer.setInterval(1000)
        self.clock_timer.timeout.connect(self.clock)
        self.clock_timer.start()
    def clock(self):
        now = datetime.now().strftime('%I:%M:%S %p')
        self.window.labels[2].setText(now)
    def update(self):
        ''' Method for updating window '''
        # Intialize Data class
        data = Data()
        # Set index variable
        index = 0
        # Loop through the data dict and update label text
        for key, val in data.weather.items():
            if key != 'image':
                self.window.labels[index].setText(str(val))
                index += 1
            if key == 'wind direction':
                text = val
       
        # Calls the Arror class and updates arror direction
        self.window.content.addWidget(self.arrow.viewarrow(direction=data.direct, \
            text=text), 9, 1,1,2, Qt.AlignmentFlag.AlignCenter)
                       
        # Sets the image label with correct image cloudy sunny, rain, etc
        pixmap = QPixmap(f'images/{data.weather['image'][1]}')
        pixmap = pixmap.scaled(120,120)
        self.window.img_label.setPixmap(pixmap)
       
        # Set the text under the image
        self.window.img_text.setText(data.weather['image'][0].title())

if __name__ == '__main__':
    app = QApplication([])
    controller = Controller(Window(), Arrow())
    app.exec()
 

Attachments

  • Kazam_screenshot_00000.png
    Kazam_screenshot_00000.png
    50.9 KB · Views: 3
Last edited:

New Threads

Buy us a coffee!

Back
Top Bottom