from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty, DictProperty
from kivy.network.urlrequest import UrlRequest
import json
from kivy.uix.listview import ListItemButton
from kivy.uix.label import Label
from kivy.factory import Factory
class LocationButton(ListItemButton):
pass
class WeatherRoot(BoxLayout):
def show_current_weather(self,location):
self.clear_widgets()
current_weather = Factory.CurrentWeather()
current_weather.location = location
self.add_widget(current_weather)
def show_add_location_form(self):
self.clear_widgets()
self.add_widget(AddLocationForm())
class AddLocationForm(BoxLayout):
search_input = ObjectProperty()
search_results = ObjectProperty()
def search_location_name(self):
search_template = 'http://api.openweathermap.org/data/2.5/' + 'find?q={}&type=like'
search_url = search_template.format(self.search_input.text)
request = UrlRequest(search_url, self.found_location_name)
if len(self.search_results.item_strings) == 0:
self.search_results.item_strings.append('City not found')
def search_location_coor(self):
try:
search_coor = self.search_input.text
search_input_coordinates = search_coor.split(',')
search_template_coordinates = 'http://api.openweathermap.org/data/2.5/' + "weather?lat=%s&lon=%s&radius=10" % (search_input_coordinates[0] , search_input_coordinates[1])
request_coordinates = UrlRequest(search_template_coordinates, self.found_location_coordinates)
except (IndexError):
self.search_results.item_strings.append('Coordinates needed are Lattitude and Longtitude!')
def found_location_coordinates(self,request_coordinates,data_coordinates):
try:
data_coordinates = json.loads(data_coordinates.decode()) if not isinstance(data_coordinates, dict) else data_coordinates
cities_coordinates = ['{} ({})'.format(data_coordinates['name'],data_coordinates['sys']['country'])]
self.search_results.item_strings = cities_coordinates
self.search_results.adapter.data[:]
self.search_results.adapter.data.extend(cities_coordinates)
self.search_results._trigger_reset_populate()
except KeyError:
self.search_results.item_strings.append('Wrong Coordinates')
def found_location_name(self, request, data):
data = json.loads(data.decode()) if not isinstance(data, dict) else data
cities = ['{} ({})'.format(d['name'],d['sys']['country']) for d in data['list']]
self.search_results.item_strings = cities
self.search_results.adapter.data[:]
self.search_results.adapter.data.extend(cities)
self.search_results._trigger_reset_populate()
if len(self.search_results.item_strings) == 0:
self.search_results.item_strings.append('City not found')
class WeatherApp(App):
pass
if __name__ == '__main__':
WeatherApp().run()
和kv文件:
#:import main main
#:import ListAdapter kivy.adapters.listadapter.ListAdapter
WeatherRoot:
<WeatherRoot>:
AddLocationForm:
orientation: 'vertical'
search_input: search_box
search_results: search_results_list
BoxLayout:
height: '40dp'
size_hint_y: None
TextInput:
id: search_box
size_hint_x: .5
Button:
text: 'Search'
size_hint_x: .25
on_press: self.parent.parent.search_location_name()
Button:
text: 'Current Location'
size_hint_x: .25
on_press: self.parent.parent.search_location_coor()
ListView:
id: search_results_list
item_strings: []
adapter:
ListAdapter(data=[], cls=main.LocationButton)
<LocationButton>:
on_press: app.root.show_current_weather(self.text)
<CurrentWeather@BoxLayout>:
location: ''
conditions: None
temp: None
temp_min: None
temp_max: None
orientation: 'vertical'
Label:
text: root.location
BoxLayout:
size_hint_y: None
height: '40dp'
Button:
text: 'Add Location'
on_press: app.root.show_add_location_form()
Button:
text: 'Forecast'
做什么和不做:
按名称或坐标搜索城市
列出了与您的搜索匹配的所有城市
您可以选择一个城市
打开黑名单,其中包含城市名称和2个按钮(添加位置和预测)
如果你点击添加位置按钮,它应该打开初始窗口,但是我得到一个黑屏,我错过了什么?
这段代码来自“使用kivy创建应用程序
”一书答案 0 :(得分:2)
我不知道这本书的目的是什么,但您提供的代码存在点击“添加位置”的问题。运行show_add_location_form
方法。
def show_add_location_form(self):
self.clear_widgets()
self.add_widget(AddLocationForm())
第一部分会清除所有小部件,为您提供黑屏。第二部分添加了一个AddLocationForm,但如果你看一下代码的其余部分,你会注意到它实际上没有定义的外观......因此屏幕保持黑色。
我通常会提出一些建议来解决它,但是因为它引用了书籍,你确定这不是故意的,而且这本书还没有完成下一步呢?
也就是说,我认为以下更改可能会起作用,从WeatherRoot规则中删除AddLocationForm的定义,以便每个 AddLocationForm实例具有相同的规则。在这种情况下,它应该通过将规则应用于新的AddLocationForm实例来使您的代码工作。我虽然没试过。
<WeatherRoot>:
AddLocationForm:
<AddLocationForm>
orientation: 'vertical'
search_input: search_box
search_results: search_results_list
BoxLayout:
height: '40dp'
size_hint_y: None
TextInput:
id: search_box
size_hint_x: .5
Button:
text: 'Search'
size_hint_x: .25
on_press: self.parent.parent.search_location_name()
Button:
text: 'Current Location'
size_hint_x: .25
on_press: self.parent.parent.search_location_coor()
ListView:
id: search_results_list
item_strings: []
adapter:
ListAdapter(data=[], cls=main.LocationButton)
请注意(假设它有效)这只是一个快速修复,如果您想要使用具有不同内容的多个屏幕,则有更好的方法来构建您的应用。我认为这本书正在进行中。