2014-06-11 5 views
0
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() 

et le fichier kv:Kivy ne présente pas un widget

#: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) 
<[email protected]>: 
    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' 

Que fait et ne marche pas faire:

  1. recherche d'une ville par son nom ou les coordonnées

  2. il liste toutes les villes qui correspondent à votre recherche

  3. vous pouvez choisir une ville

  4. ouvre la page noire avec la ville le nom et 2 boutons (Ajouter un emplacement et prévisions)

Si vous cliquez sur le bouton de l'emplacement de l'ajouter devrait ouvrir la fenêtre initiale , mais à la place j'ai un écran noir. Suis-je en train de manquer quelque chose?

Ce fut code a été tiré du livre Création d'applications avec Kivy

+0

Alors que je suis enclin à vérifier cela, étant donné qu'il provient d'un livre, pouvez-vous confirmer que vous n'avez aucun problème avec les versions? Vous n'êtes pas familier avec la référence que vous utilisez, mais Kivy a eu quelques petites mises à jour cette année. Si la référence n'est pas mise à jour, il pourrait y avoir le problème. – Manhattan

Répondre

2

Je ne sais pas ce que le livre a l'intention, mais le code que vous avez donné a le problème en cliquant sur « Ajouter emplacement » court le show_add_location_form. La première partie de ceci efface tous vos widgets, vous donnant cet écran noir. La deuxième partie ajoute un AddLocationForm, mais si vous regardez le reste du code, vous remarquerez que cela n'a pas d'apparence définie ... donc l'écran reste noir.

Je donnerais normalement quelques suggestions pour le résoudre, mais puisque c'est un devis de livre, êtes-vous sûr que ce n'est pas délibéré et que le livre n'a pas encore fait le prochain morceau? Cela dit, je pense que la modification suivante fonctionnera probablement, supprimant la définition de AddLocationForm de la règle WeatherRoot de sorte que chaque instance AddLocationForm ait la même règle. Dans ce cas, votre code devrait fonctionner en appliquant la règle à la nouvelle instance AddLocationForm. Je n'ai pas essayé cependant.

<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) 

Notez que (en supposant qu'il fonctionne) c'est juste une solution rapide, il y a de meilleures façons de structurer votre application si vous souhaitez utiliser plusieurs écrans avec un contenu différent. Je suppose que le livre arrive à cela.