2017-08-14 5 views
0

Was wäre eine gute Möglichkeit, Widgets aus Python-Code (dynamisch) zu einem Bildschirm hinzuzufügen?Python Kivy: Dynamisches Hinzufügen von Widgets zu einem Bildschirm

Mein Ziel ist es, zwei "Haupt" -Bildschirme zu haben. Der Inhalt des zweiten Bildschirms hängt davon ab, was auf dem Hauptbildschirm ausgewählt wurde. Dieser Inhalt kann der Einfachheit halber als eine variable Anzahl von Schaltflächen angesehen werden (alle Inhalte wie die Anzahl der Schaltflächen, Hintergrundbilder usw., die in der Datenbank gespeichert und unabhängig aktualisiert werden). So stelle ich mir die Logik folgendermaßen vor: Wenn die MainScreen-Taste gedrückt wird, gehe ich zur Datenbank und lade die Daten mit der Taste 'Taste N' ab und zeige sie auf dem zweiten Bildschirm in Form von angepassten Button/Label-Widgets an. Ich möchte auch zum MainScreen zurückkehren, um bei Bedarf eine andere Taste auszuwählen.

Lets ich zwei Bildschirme übernehmen haben, die statische Grafiken in KV-Datei definiert ist:

<MainScreen> 
    BoxLayout: 
     orientation: "vertical" 
     Label: 
      text: "SELECT BUTTON" 
     Button: 
      on_press: root.show_buttons(self) 
      text: "Button 1" 
     Button: 
      on_press: root.show_buttons(self) 
      text: "Button 2" 

<AnotherScreen>: 
    BoxLayout: 
     orientation: 'vertical' 
     Label: 
      text: "Select BUTTON" 
     Button: 
      on_press: root.manager.current = 'Main' 
      text: "BACK" 

Mainscreen ist voll statisch. Wenn eine Taste gedrückt wird, muss ich AnotherScreen aufrufen und je nachdem, welche Taste gedrückt wird, Inhalte hinzufügen. Ich machte einen Versuch, es zu tun, wie folgt (und nicht):

class MainScreen(Screen): 
    def show_buttons(self, btn): 
     if btn.text == 'Button 1': 
      another_screen.add_widget(Label(text="Button 1 pressed")) 
      sm.current = "Another" 
      return sm 

class AnotherScreen(Screen): 
    pass 

class CoolApp(App): 
    def build(self): 
     global sm 
     sm = ScreenManager() 
     main_screen = MainScreen(name='Main') 
     sm.add_widget(main_screen) 
     global another_screen 
     another_screen = AnotherScreen(name='Another') 
     sm.add_widget(another_screen) 
     return sm 


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

In diesem Fall dynamischer Widget another_screen.add_widget(Label(text="Button pressed")) wird auf einen Bildschirm hinzugefügt, die von defintion nur ein Kind (bereits definiert in KV) haben kann. Ich habe keine Ausnahme bekommen, aber ich habe zwei verschiedene Widgets zur gleichen Zeit gerendert, was genauso schlimm ist.

Ich denke, ich muss dynamische Widgets BoxLayout hinzufügen, weil es das Root-Widget des Bildschirms ist. Allerdings weiß ich nicht, ob es möglich ist, Widget aus verschiedenen Klassen zu referenzieren, und wenn ja, ist das angemessen?

Vielen Dank!

Antwort

0

Eine Möglichkeit ist die Verwendung von IDs.

from kivy.uix.screenmanager import ScreenManager, Screen 
from kivy.app import App 
from kivy.lang import Builder 
from kivy.uix.label import Label 

class MainScreen(Screen): 
    first_btn_press = True 
    def show_buttons(self, btn): 
     if btn.text == 'Button 1': 
      print(self.manager.ids) 
      if self.first_btn_press: 
       self.manager.ids.another.ids.box.add_widget(Label(text="Button 1 pressed")) 
       self.first_btn_press = False 
      self.manager.current = "another" 

class AnotherScreen(Screen): 
    pass 

kv_str = Builder.load_string(""" 
ScreenManager: 
    MainScreen: 
     id: main 
    AnotherScreen: 
     id: another 


<MainScreen> 
    name: "main" 
    BoxLayout: 
     orientation: "vertical" 
     Label: 
      text: "SELECT BUTTON" 
     Button: 
      on_press: root.show_buttons(self) 
      text: "Button 1" 
     Button: 
      on_press: root.show_buttons(self) 
      text: "Button 2" 

<AnotherScreen>: 
    id: another 
    name: "another" 
    BoxLayout: 
     id: box 
     orientation: 'vertical' 
     Label: 
      text: "Select BUTTON" 
     Button: 
      on_press: root.manager.current = 'main' 
      text: "BACK" 


""") 



class CoolApp(App): 
    def build(self): 
     return kv_str 


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

Am Ende liegt es an Ihnen. Eine andere Möglichkeit wäre die Verwendung von ObjectProperties im ScreenManager oder direkt in der App-Klasse. Die obige Lösung ist meine bevorzugte Vorgehensweise.

+0

Danke! Ich habe auch diesen Ansatz versucht, aber das Problem ist, dass, wenn ich den zweiten Bildschirm mehrere Male aufrufen, wird es zur Hinzufügung von mehreren gleichen Tasten dazu führen. Deshalb habe ich den Button "Zurück": Ich möchte bei Bedarf zum MainScreen zurückkehren. Wenn ich nach der Rückkehr noch einmal auf "Taste 1" drücke, habe ich zwei Etiketten "Taste 1 gedrückt". – Agenobarb

+0

Wenn dies nicht Ihr gewünschtes Verhalten ist, können Sie einfach einen booleschen Wert hinzufügen, den Sie ändern, sobald die Schaltfläche zusammen mit einer if-Klausel gedrückt wurde. Beim nächsten Mal wird nur der Bildschirm gewechselt. Ich kann das vielleicht morgen hinzufügen. – PalimPalim

+0

Bitte fügen Sie auch weitere Details zu Ihrer Frage hinzu. So ist es einfacher zu verstehen, was Ihr Ziel ist. – PalimPalim

Verwandte Themen