9

I am using the Kivy python library.

I have two widgets defined.

When the program runs, I run the first widget.

When that widgets button is pressed, I want it to dissapear and be replaced with the second widget.

Here is the .kv for the two widgets

#uitest.kv
<TestForm>:
    canvas:
        Rectangle:
            pos: self.center_x, 0
            size: 10, self.height

    BoxLayout:
        size: root.size
        padding: 40
        Button:
            text: 'Hello'
            on_release: root.testCallback()

<TestForm2>:
    canvas:
        Rectangle:
            pos: self.center_x, 0
            size: self.height, 10

My main python file runs the app, and returns the first widget

#main.py
from testform import TestForm
from kivy.app import App

class UITestApp(App):
    def build(self):
        return TestForm()

# Main launching point
if __name__ in ('__main__', '__android__'):
    UITestApp().run()

My first widget has a callback. This is where the code-in-question belongs

from testform2 import TestForm2
from kivy.uix.widget import Widget

class TestForm(Widget):
    def testCallback(self):
        TestForm2() # Code in question goes here. @TODO replace this widget with TestForm2 widget.

The idea here is to have a user interface manager. This manager doesn't run the UI like a tree, but like a list and stack. The list holds instances of all my UI Forms. The stack holds the traversal of said forms, whenever we jump to a form we push it to the stack and "render" or whatever that one.

EDIT: I chose my answer, but in my searches I also found the Screen object: http://kivy.org/docs/api-kivy.uix.screenmanager.html Personally, the clear() and add() commands are more powerful, but the screen takes a lot of that out of your hands if you're interested. Transition effects too.

MintyAnt
  • 2,978
  • 7
  • 25
  • 37

2 Answers2

11

My suggestion is to have an interface manager widget, then you can have various widgets for your UI forms.

import kivy
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App

class InterfaceManager(BoxLayout):

    def __init__(self, **kwargs):
        super(InterfaceManager, self).__init__(**kwargs)

        self.first = Button(text="First")
        self.first.bind(on_press=self.show_second)

        self.second = Button(text="Second")
        self.second.bind(on_press=self.show_final)

        self.final = Label(text="Hello World")
        self.add_widget(self.first)

    def show_second(self, button):
        self.clear_widgets()
        self.add_widget(self.second)

    def show_final(self, button):
        self.clear_widgets()
        self.add_widget(self.final)


class MyApp(App):
    def build(self):
        return InterfaceManager(orientation='vertical')

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

You wouldn't structure it like that of course. You could hold all your forms in a dictionary on the Container object and have a universal callback which provides another form by key.

class InterfaceManager(BoxLayout):

    def __init__(self, **kwargs):
        super(InterfaceManager, self).__init__(**kwargs)
        self.forms = {}

    def add_form(self, key, form):
        self.forms[key] = form

    def uniCallback(self, button):
        self.clear_widgets()
        # You could introduce a more elegant key
        # handling system here.
        self.add_widget(self.forms[button.text])
Adam
  • 4,180
  • 2
  • 27
  • 31
  • clear_widgets() and add_widget() were the secret commands I was missing, thanks a lot. No ammount of searching turned them up, only the "screen" object – MintyAnt Feb 05 '13 at 18:03
  • 2
    [The docs](http://kivy.org/docs/api-kivy.uix.widget.html) are excellent for kivy and it's probably worth just browsing down the right hand side where all the different widgets are listed. There's loads of stuff I was trying to reinvent when I first found the library. – Adam Feb 05 '13 at 19:49
  • 2
    Can you give the same in Kivy language. Mixing kivy klanguage with python is making me confused! – Wally Aug 14 '14 at 02:42
  • @user3620828: It's probably worth raising another question. Remember to provide examples of what you've tried so far. – Adam Aug 14 '14 at 07:45
5

A simple way to switch widgets is to let one be the full height of its container and let the second one have a height of zero. When you need to switch just swap the heights around.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Certaintly an interestin option! But I plan on having many widgets, and if I want to purge some from memory this might not be the best idea – MintyAnt Feb 05 '13 at 18:02
  • @MintyAnt, in my own application I only have 2 widgets to switch between and this method works well for me. I'm sorry it didn't fit your use case. – Mark Ransom Feb 05 '13 at 18:05