Advertisement
peachyontop

rstjsryjrtjr6

Apr 4th, 2025
8
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.87 KB | None | 0 0
  1. import requests
  2. from kivy.metrics import dp
  3. from kivy.clock import Clock
  4. from kivy.lang import Builder
  5. from kivy.utils import platform
  6. from kivymd.app import MDApp
  7. from kivymd.uix.screen import MDScreen
  8. from kivymd.uix.boxlayout import MDBoxLayout
  9. from kivymd.uix.label import MDLabel
  10. from kivymd.uix.toolbar import MDTopAppBar
  11. from kivymd.uix.card import MDCard
  12. from threading import Thread
  13. from datetime import datetime
  14. from dateutil import parser
  15.  
  16. Builder.load_string('''
  17. <WeatherScreen>:
  18. MDBoxLayout:
  19. orientation: 'vertical'
  20.  
  21. MDTopAppBar:
  22. title: "Weather App"
  23. elevation: 4
  24. left_action_items: [['arrow-left', lambda x: app.go_back()]]
  25. right_action_items: [['refresh', lambda x: root.refresh()]]
  26.  
  27. ScrollView:
  28. MDBoxLayout:
  29. orientation: 'vertical'
  30. spacing: dp(20)
  31. padding: dp(20)
  32. size_hint_y: None
  33. height: self.minimum_height
  34.  
  35. MDCard:
  36. id: main_card
  37. orientation: 'vertical'
  38. size_hint_y: None
  39. height: dp(200)
  40. padding: dp(20)
  41. spacing: dp(10)
  42. elevation: 2
  43.  
  44. MDBoxLayout:
  45. spacing: dp(20)
  46. size_hint_y: None
  47. height: dp(80)
  48. pos_hint: {'center_y': 0.5}
  49.  
  50. MDLabel:
  51. id: weather_icon
  52. text: "⛅"
  53. font_size: dp(48)
  54. halign: 'center'
  55. size_hint_x: None
  56. width: dp(80)
  57.  
  58. MDLabel:
  59. id: temp_label
  60. text: "--°C"
  61. font_style: 'H2'
  62. bold: True
  63. halign: 'center'
  64.  
  65. MDLabel:
  66. id: location_label
  67. text: "Locating..."
  68. halign: 'center'
  69. font_style: 'Subtitle1'
  70.  
  71. MDLabel:
  72. id: update_label
  73. text: "Last update: --"
  74. halign: 'center'
  75. font_style: 'Caption'
  76.  
  77. MDCard:
  78. id: details_card
  79. size_hint_y: None
  80. height: dp(120)
  81. padding: dp(20)
  82. elevation: 2
  83.  
  84. MDGridLayout:
  85. cols: 3
  86. spacing: dp(20)
  87.  
  88. DetailItem:
  89. icon: "💨"
  90. value: "-- km/h"
  91. label: "Wind"
  92.  
  93. DetailItem:
  94. icon: "💧"
  95. value: "--%"
  96. label: "Humidity"
  97.  
  98. DetailItem:
  99. icon: "đŸŒ§ī¸"
  100. value: "-- mm"
  101. label: "Rain"
  102.  
  103. MDCard:
  104. id: forecast_card
  105. size_hint_y: None
  106. height: dp(150)
  107. padding: dp(20)
  108. elevation: 2
  109.  
  110. MDLabel:
  111. text: "Hourly Forecast"
  112. font_style: 'H6'
  113. bold: True
  114.  
  115. ScrollView:
  116. do_scroll_x: True
  117. do_scroll_y: False
  118. MDBoxLayout:
  119. id: forecast_container
  120. orientation: 'horizontal'
  121. spacing: dp(15)
  122. size_hint_x: None
  123. width: self.minimum_width
  124.  
  125. <DetailItem@MDBoxLayout>:
  126. orientation: 'vertical'
  127. spacing: dp(5)
  128. size_hint_x: None
  129. width: dp(100)
  130.  
  131. MDLabel:
  132. text: root.icon
  133. font_size: dp(24)
  134. halign: 'center'
  135.  
  136. MDLabel:
  137. text: root.value
  138. font_style: 'H6'
  139. halign: 'center'
  140. bold: True
  141.  
  142. MDLabel:
  143. text: root.label
  144. font_style: 'Caption'
  145. halign: 'center'
  146. ''')
  147.  
  148. class WeatherScreen(MDScreen):
  149. def on_enter(self):
  150. self.refresh()
  151.  
  152. def refresh(self):
  153. self.ids.temp_label.text = "--°C"
  154. self.ids.location_label.text = "Locating..."
  155. self.ids.update_label.text = "Updating..."
  156. Thread(target=self.fetch_weather, daemon=True).start()
  157.  
  158. def fetch_weather(self):
  159. try:
  160. lat, lon = 48.1351, 11.5820 # Munich coordinates
  161. response = requests.get(
  162. f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}"
  163. "&current_weather=true&hourly=temperature_2m,precipitation_probability"
  164. )
  165. data = response.json()
  166.  
  167. current = data.get('current_weather', {})
  168. hourly = data.get('hourly', {}).get('temperature_2m', [])[:6]
  169. time_data = data.get('hourly', {}).get('time', [])[:6]
  170.  
  171. Clock.schedule_once(lambda dt: self.update_ui(
  172. temp=current.get('temperature', '--'),
  173. wind=current.get('windspeed', '--'),
  174. time=current.get('time', ''),
  175. forecast=list(zip(hourly, time_data))
  176. )
  177. except Exception as e:
  178. Clock.schedule_once(lambda dt: self.show_error(str(e)))
  179.  
  180. def update_ui(self, temp, wind, time, forecast):
  181. # Main card
  182. self.ids.temp_label.text = f"{temp}°C"
  183. self.ids.weather_icon.text = self.get_weather_icon()
  184.  
  185. # Location and time
  186. self.ids.location_label.text = "Munich, DE"
  187. try:
  188. dt = parser.isoparse(time).strftime("%H:%M")
  189. self.ids.update_label.text = f"Updated: {dt}"
  190. except:
  191. self.ids.update_label.text = "Updated: Now"
  192.  
  193. # Details
  194. details = self.ids.details_card.children[0].children
  195. details[0].value = f"{wind} km/h"
  196. details[1].value = "65%"
  197. details[2].value = "0 mm"
  198.  
  199. # Forecast
  200. container = self.ids.forecast_container
  201. container.clear_widgets()
  202. for temp, time_str in forecast:
  203. container.add_widget(self.create_forecast_item(temp, time_str))
  204.  
  205. def create_forecast_item(self, temp, time_str):
  206. try:
  207. hour = parser.isoparse(time_str).strftime("%H:%M")
  208. except:
  209. hour = time_str[-5:]
  210.  
  211. item = MDBoxLayout(
  212. orientation='vertical',
  213. spacing=dp(5),
  214. size_hint_x=None,
  215. width=dp(80)
  216.  
  217. item.add_widget(MDLabel(
  218. text=f"{temp}°",
  219. font_style='H6',
  220. halign='center'
  221. ))
  222. item.add_widget(MDLabel(
  223. text=hour,
  224. font_style='Caption',
  225. halign='center'
  226. ))
  227. return item
  228.  
  229. def get_weather_icon(self):
  230. icons = ["â˜€ī¸", "⛅", "đŸŒ§ī¸", "â„ī¸", "đŸŒŠī¸"]
  231. return icons[datetime.now().hour % 5]
  232.  
  233. def show_error(self, message):
  234. self.ids.temp_label.text = "Error"
  235. self.ids.location_label.text = "Check connection"
  236. self.ids.update_label.text = message[:30]
  237.  
  238. class WeatherApp(MDApp):
  239. def build(self):
  240. self.theme_cls.theme_style = "Dark"
  241. self.theme_cls.primary_palette = "Blue"
  242. return WeatherScreen()
  243.  
  244. def go_back(self):
  245. self.stop()
  246.  
  247. if __name__ == '__main__':
  248. WeatherApp().run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement