2016-05-12 95 views
0

Ich versuche eine App zu erstellen, die Daten vom MySQL-Server verwendet. Bisher ging es mir gut, bis ich über die Notwendigkeit stolperte, die Labels zu aktualisieren.So aktualisieren Sie dynamisch Kivy-Labels, nachdem Sie die Taste gedrückt haben

Dies ist, was ich bisher:

from kivy.uix.button import Button 
from kivy.lang import Builder 
from kivy.uix.screenmanager import ScreenManager, Screen 
from kivy.uix.label import Label 
from kivy.uix.scrollview import ScrollView 
from kivy.clock import Clock 
import MySQLdb 
class MainView(ScrollView): 

    def qchange(self): 
     query = 'SELECT * FROM `citiestovisit` ORDER BY `idcitiestovisit`' 
     self.db_data(query) 
    q = 'SELECT * FROM `citiestovisit` ORDER BY `Name`' 
    def db_data(self, query=q): 
     #vector = ListProperty() 
     vector = [] 
     con = MySQLdb.connect(host="localhost", user="root", passwd="", db="cities") 
     cur = con.cursor() 
     cur.execute('SET NAMES `utf8`') 
     cur.execute(query) 
     result = cur.fetchall() 
     for row in result: 
      string = str(row[0]) + " " + str(row[1]) + " " + str(row[2]) 
      vector.append(string) 
     print vector 
     return vector 
    def __init__(self, **kwargs): 
     kwargs['cols'] = 2 
     super(MainView, self).__init__(**kwargs) 
     GL = GridLayout(cols = 3, spacing=10, size_hint_y=None) 
     GL.bind(minimum_height=GL.setter('height')) 
     for row in self.db_data(): 
      splitRow = row.split(" ") 
      for data in splitRow: 
       GL.add_widget(Label(text=data,size_hint_y=None, font_size='20sp')) 
     self.add_widget(GL) 
Builder.load_string(""" 
<MenuScreen>: 
    BoxLayout: 
     GridLayout: 
      cols: 1 
      Button: 
       text: 'Goto settings' 
       on_press: 
        root.manager.transition.direction = 'left' 
        root.manager.current = 'settings' 
      Button: 
       text: 'Quit' 
     Label: 
      font_name: 'C:\Anonymous\Anonymous.ttf' 
      text: "picture here" 

<SettingsScreen>: 
""") 

# Declare both screens 
class MenuScreen(Screen): 
    pass 

class SettingsScreen(Screen): 
    pass 

ss = SettingsScreen(name='settings') 
layout = BoxLayout(orientation='vertical') 
BL = BoxLayout() 
layout.add_widget(BL) 

#Instance of a MainView class 

MV = MainView() 

def callback(instance): 
    sm.transition.direction = 'right' 
    sm.current = 'menu' 
def callback2(instance): 
    MV.qchange() 



btn = Button(text="Back to Menu") 
btn.bind(on_press=callback) 
btn.size_hint = (1, 0.3) 
BL.add_widget(btn) 

btn2 = Button(text="Sort by ID") 
btn2.size_hint = (1, 0.3) 
btn2.bind(on_press=callback2) 
BL.add_widget(btn2) 

layout.add_widget(MainView()) 

sublayout = GridLayout(cols=3) 
sublayout.add_widget(Label(text="hello")) 
sublayout.add_widget(Label(text="World")) 
sublayout.add_widget(Label(text="Python")) 
layout.add_widget(sublayout) 

ss.add_widget(layout) 

# Create the screen manager 
sm = ScreenManager() 
sm.add_widget(MenuScreen(name='menu')) 
sm.add_widget(ss) 

class MyApp(App): 
    def build(self): 
     return sm 

if __name__ == '__main__': 
    MyApp().run() 

Ich bin besonders interessiert in def qchange(self) mehod wie es in def db_data(self, query=q) geht eine neue Abfrage; Als Ergebnis wird eine Anfrage an die Datenbank gesendet und ein Array von Strings zurückgegeben. Dieses Array wird jedoch nicht weiter verarbeitet, und die Beschriftungen im GL-Widget werden nicht aktualisiert. Ich denke, ich muss die Uhr hinzufügen, die die __init__ in MainView nennen würde, aber es ist nur eine Vermutung, wie ich auch über die Verwendung von Eigenschaften gelesen habe (die ich nicht hier auch verwenden kann)

I ' Habe meinen Code editiert. Jetzt sieht es wie folgt aus:

class MainView(ScrollView): 

    def qchange(self): 

     query = 'SELECT * FROM `citiestovisit` ORDER BY `idcitiestovisit`' 
     #self.db_data(query) 
     #LG = self.LabelsGrid(self.GL) 

    q = 'SELECT * FROM `citiestovisit` ORDER BY `Name`' 

    def db_data(self, query=q): 

     vector = [] 

     con = MySQLdb.connect(host="localhost", user="root", passwd="", db="cities") 
     cur = con.cursor() 
     cur.execute('SET NAMES `utf8`') 
     cur.execute(query) 

     result = cur.fetchall() 

     for row in result: 
      string = str(row[0]) + " " + str(row[1]) + " " + str(row[2]) 

      vector.append(string) 

     print vector 
     return vector 

    class LabelsGrid(GridLayout): 
     def __init__(self, **kwargs): 
      self.cols = 3 
      self.spacing = 10 
      self.size_hint_y = None 

     def show_labels(self, strings): 
      self.clear_widgets() 

      for row in strings: 
       splitRow = row.split(" ") 
       for data in splitRow: 
        label = Label(text=data, size_hint_y=None, font_size='20sp') 
        self.add_widget(label) 



    GL = LabelsGrid() 
    def __init__(self, **kwargs): 
     kwargs['cols'] = 2 
     super(MainView, self).__init__(**kwargs) 
     self.GL=self.LabelsGrid() 
     # GL = GridLayout(cols = 3, spacing=10, size_hint_y=None) 
     self.GL.bind(minimum_height=self.GL.setter('height')) 

     self.GL.show_labels(self.db_data(self.q)) 

     self.add_widget(self.GL) 

     #self.GL.clear_widgets() 

Builder.load_string(""" 

<MenuScreen>: 
    BoxLayout: 
     GridLayout: 
      cols: 1 
      Button: 
       text: 'Goto settings' 
       on_press: 
        root.manager.transition.direction = 'left' 
        root.manager.current = 'settings' 
      Button: 
       text: 'Quit' 
     Label: 
      font_name: 'C:\Anonymous\Anonymous.ttf' 
      text: "picture here" 

<SettingsScreen>: 


""") 

# Declare both screens 
class MenuScreen(Screen): 
    pass 

class SettingsScreen(Screen): 
    pass 

ss = SettingsScreen(name='settings') 
layout = BoxLayout(orientation='vertical') 
BL = BoxLayout() 
layout.add_widget(BL) 

#Instance of a MainView class 

MV = MainView() 

def callback(instance): 
    sm.transition.direction = 'right' 
    sm.current = 'menu' 
def callback2(instance): 
    MV.qchange() 



btn = Button(text="Back to Menu") 
btn.bind(on_press=callback) 
btn.size_hint = (1, 0.3) 
BL.add_widget(btn) 

btn2 = Button(text="Sort by ID") 
btn2.size_hint = (1, 0.3) 
btn2.bind(on_press=callback2) 
BL.add_widget(btn2) 

layout.add_widget(MainView()) 

sublayout = GridLayout(cols=3) 
sublayout.add_widget(Label(text="hello")) 
sublayout.add_widget(Label(text="World")) 
sublayout.add_widget(Label(text="Python")) 
layout.add_widget(sublayout) 

ss.add_widget(layout) 

# Create the screen manager 
sm = ScreenManager() 
sm.add_widget(MenuScreen(name='menu')) 
sm.add_widget(ss) 

class MyApp(App): 
    def build(self): 
     return sm 

if __name__ == '__main__': 
    MyApp().run() 

Durch die Zugabe von

class LabelsGrid(GridLayout): 
      def __init__(self, **kwargs): 
       self.cols = 3 
       self.spacing = 10 
       self.size_hint_y = None 

      def show_labels(self, strings): 
       self.clear_widgets() 

       for row in strings: 
        splitRow = row.split(" ") 
        for data in splitRow: 
         label = Label(text=data, size_hint_y=None, font_size='20sp') 
         self.add_widget(label) 

Ich wollte Brauch hinzufügen Gridlayout nach einem bestimmten Ratschlag aber jetzt bekomme ich eine Fehlermeldung,:

AttributeError: 'LabelsGrid' object has no attribute '_trigger_layout' 

Irgendwelche Ideen, wie man damit umgeht?

Antwort

0

Erstellen Sie ein benutzerdefiniertes Rasterlayout, sagen wir LabelsGrid, und implementieren Sie in der Klasse eine Methode show_labels. Beispiel:

class LabelsGrid(GridLayout): 

    def show_labels(self, strings): 
     self.clear_widgets() 

     for text in strings: 
      label = Label(text=text) 
      self.add_widget(label) 

Auf diese Weise jedes Mal, wenn Sie die Methode mit Namen von Etiketten in einer Liste aufrufen, wird es selbst aktualisieren.

+0

Könnten Sie, bitte, erklären, weil ich bereits ein GridLayout Widget in __init__ Methode habe. Gemäß Ihrem Vorschlag sollte ich diese Klasse zur MainView-Klasse hinzufügen, nicht wahr? Und was soll ich mit dem GL-Widget machen, das bereits ein GridLayout ist? –

+0

@JohnAward Ersetzen Sie das alte Rasterlayout durch dieses benutzerdefinierte Rasterlayout. – jligeza