Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import requests
- from kivy.metrics import dp
- from kivy.clock import Clock
- from kivy.lang import Builder
- from kivy.utils import platform
- from kivymd.app import MDApp
- from kivymd.uix.screen import MDScreen
- from kivymd.uix.boxlayout import MDBoxLayout
- from kivymd.uix.label import MDLabel
- from kivymd.uix.toolbar import MDTopAppBar
- from kivymd.uix.card import MDCard
- from threading import Thread
- from datetime import datetime
- from dateutil import parser
- Builder.load_string('''
- <WeatherScreen>:
- MDBoxLayout:
- orientation: 'vertical'
- MDTopAppBar:
- title: "Weather App"
- elevation: 4
- left_action_items: [['arrow-left', lambda x: app.go_back()]]
- right_action_items: [['refresh', lambda x: root.refresh()]]
- ScrollView:
- MDBoxLayout:
- orientation: 'vertical'
- spacing: dp(20)
- padding: dp(20)
- size_hint_y: None
- height: self.minimum_height
- MDCard:
- id: main_card
- orientation: 'vertical'
- size_hint_y: None
- height: dp(200)
- padding: dp(20)
- spacing: dp(10)
- elevation: 2
- MDBoxLayout:
- spacing: dp(20)
- size_hint_y: None
- height: dp(80)
- pos_hint: {'center_y': 0.5}
- MDLabel:
- id: weather_icon
- text: "â "
- font_size: dp(48)
- halign: 'center'
- size_hint_x: None
- width: dp(80)
- MDLabel:
- id: temp_label
- text: "--°C"
- font_style: 'H2'
- bold: True
- halign: 'center'
- MDLabel:
- id: location_label
- text: "Locating..."
- halign: 'center'
- font_style: 'Subtitle1'
- MDLabel:
- id: update_label
- text: "Last update: --"
- halign: 'center'
- font_style: 'Caption'
- MDCard:
- id: details_card
- size_hint_y: None
- height: dp(120)
- padding: dp(20)
- elevation: 2
- MDGridLayout:
- cols: 3
- spacing: dp(20)
- DetailItem:
- icon: "đ¨"
- value: "-- km/h"
- label: "Wind"
- DetailItem:
- icon: "đ§"
- value: "--%"
- label: "Humidity"
- DetailItem:
- icon: "đ§ī¸"
- value: "-- mm"
- label: "Rain"
- MDCard:
- id: forecast_card
- size_hint_y: None
- height: dp(150)
- padding: dp(20)
- elevation: 2
- MDLabel:
- text: "Hourly Forecast"
- font_style: 'H6'
- bold: True
- ScrollView:
- MDBoxLayout:
- id: forecast_container
- orientation: 'horizontal'
- spacing: dp(15)
- size_hint_x: None
- width: self.minimum_width
- <DetailItem@MDBoxLayout>:
- orientation: 'vertical'
- spacing: dp(5)
- size_hint_x: None
- width: dp(100)
- MDLabel:
- text: root.icon
- font_size: dp(24)
- halign: 'center'
- MDLabel:
- text: root.value
- font_style: 'H6'
- halign: 'center'
- bold: True
- MDLabel:
- text: root.label
- font_style: 'Caption'
- halign: 'center'
- ''')
- class WeatherScreen(MDScreen):
- def on_enter(self):
- self.refresh()
- def refresh(self):
- self.ids.temp_label.text = "--°C"
- self.ids.location_label.text = "Locating..."
- self.ids.update_label.text = "Updating..."
- Thread(target=self.fetch_weather, daemon=True).start()
- def fetch_weather(self):
- try:
- # Get sample data
- lat, lon = 48.1351, 11.5820 # Munich coordinates
- response = requests.get(
- f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}"
- "¤t_weather=true&hourly=temperature_2m,precipitation_probability"
- )
- data = response.json()
- current = data.get('current_weather', {})
- hourly = data.get('hourly', {}).get('temperature_2m', [])[:12]
- Clock.schedule_once(lambda dt: self.update_ui(
- temp=current.get('temperature', '--'),
- wind=current.get('windspeed', '--'),
- time=current.get('time', ''),
- forecast=hourly
- ))
- except Exception as e:
- Clock.schedule_once(lambda dt: self.show_error(str(e)))
- def update_ui(self, temp, wind, time, forecast):
- # Main card
- self.ids.temp_label.text = f"{temp}°C"
- self.ids.weather_icon.text = self.get_weather_icon()
- # Location and time
- self.ids.location_label.text = "Munich, DE"
- try:
- dt = parser.isoparse(time).strftime("%H:%M")
- self.ids.update_label.text = f"Updated: {dt}"
- except:
- self.ids.update_label.text = "Updated: Now"
- # Details
- details = self.ids.details_card.children[0].children
- details[0].value = f"{wind} km/h"
- details[1].value = "65%"
- details[2].value = "0 mm"
- # Forecast
- container = self.ids.forecast_container
- container.clear_widgets()
- for temp in forecast[:6]: # Show 6 items for mobile
- container.add_widget(ForecastItem(temp=temp))
- def get_weather_icon(self):
- icons = ["âī¸", "â ", "đ§ī¸", "âī¸", "đŠī¸"]
- return icons[datetime.now().hour % 5]
- def show_error(self, message):
- self.ids.temp_label.text = "Error"
- self.ids.location_label.text = "Check connection"
- self.ids.update_label.text = message[:30]
- class ForecastItem(MDBoxLayout):
- def __init__(self, temp, **kwargs):
- super().__init__(**kwargs)
- self.orientation = 'vertical'
- self.spacing = dp(5)
- self.size_hint_x = None
- self.width = dp(80)
- self.add_widget(MDLabel(
- text=f"{temp}°",
- font_style='H6',
- halign='center'
- ))
- self.add_widget(MDLabel(
- text=f"{datetime.now().hour % 24:02d}:00",
- font_style='Caption',
- halign='center'
- ))
- class WeatherApp(MDApp):
- def build(self):
- self.theme_cls.theme_style = "Dark"
- self.theme_cls.primary_palette = "Blue"
- return WeatherScreen()
- def go_back(self):
- self.stop()
- if __name__ == '__main__':
- WeatherApp().run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement