Kivy: изменение экранов в диспетчере экрана с помощью пресс-мероприятия
Я хотел бы знать, как изменить экраны с помощью события on_press, привязанного к кнопке, без использования языка KV-файла/KV.
Я прочитал документацию Kivy, но смог найти решения только с помощью файла KV.
пример:
on_press: root.manager.current = 'screen2'
Я также могу изменить экран в главном файле python, используя:
screenmanager.current = 'screen2'
но я не могу понять, как добиться того же с помощью кнопки.
3 ответов
один простой способ сделать это, чтобы определить свой собственный подкласс кнопки:
class ScreenButton(Button):
screenmanager = ObjectProperty()
def on_press(self, *args):
super(ScreenButton, self).on_press(*args)
self.screenmanager.current = 'whatever'
метод on_press автоматически вызывается при нажатии кнопки, поэтомуcurrent
свойство будет изменено.
тогда у вас может быть код что-то вроде:
sm = ScreenManager()
sc1 = Screen(name='firstscreen')
sc1.add_widget(ScreenButton(screenmanager=sm))
sc2 = Screen(name='whatever')
sc2.add_widget(Label(text='another screen'))
sm.add_widget(sc1)
sm.add_widget(sc2)
нажатие кнопки должно переключать экраны по мере необходимости.
другой способ (который, вероятно, как KV язык на самом деле делает это) будет вручную использовать bind
метод.
def switching_function(*args):
some_screen_manager.current = 'whatever'
some_button.bind(on_press=switching_function)
это будет означать, что switching_function
вызывается всякий раз, когда some_button
нажата. Конечно, здесь есть много гибкости в отношении того, как и когда вы определяете функцию, поэтому (например) вы можете сделать что-то более общее, например, передать screenmanager в качестве первого аргумента функции.
Я не тестировал этот код, и это не полное приложение, но, надеюсь, смысл ясен. Любой из методов должен работать нормально, вы можете выбрать способ, которым кажется, это разумно. Я мог бы построить более полный пример позже.
рабочий пример с двумя экранами, нет KV-файла все сделано в Python:
import kivy
kivy.require('1.8.0')
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
class ScreenOne(Screen):
def __init__ (self,**kwargs):
super (ScreenOne, self).__init__(**kwargs)
my_box1 = BoxLayout(orientation='vertical')
my_label1 = Label(text="BlaBlaBla on screen 1", font_size='24dp')
my_button1 = Button(text="Go to screen 2",size_hint_y=None, size_y=100)
my_button1.bind(on_press=self.changer)
my_box1.add_widget(my_label1)
my_box1.add_widget(my_button1)
self.add_widget(my_box1)
def changer(self,*args):
self.manager.current = 'screen2'
class ScreenTwo(Screen):
def __init__(self,**kwargs):
super (ScreenTwo,self).__init__(**kwargs)
my_box1 = BoxLayout(orientation='vertical')
my_label1 = Label(text="BlaBlaBla on screen 2",font_size='24dp')
my_button1 = Button(text="Go to screen 1",size_hint_y=None, size_y=100)
my_button1.bind(on_press=self.changer)
my_box1.add_widget(my_label1)
my_box1.add_widget(my_button1)
self.add_widget(my_box1)
def changer(self,*args):
self.manager.current = 'screen1'
class TestApp(App):
def build(self):
my_screenmanager = ScreenManager()
screen1 = ScreenOne(name='screen1')
screen2 = ScreenTwo(name='screen2')
my_screenmanager.add_widget(screen1)
my_screenmanager.add_widget(screen2)
return my_screenmanager
if __name__ == '__main__':
TestApp().run()
другим решением было использовать setter
метод EventDispatcher, чтобы получить ссылку на функцию setter для screen_manager.ток
button.bind(on_press=partial(sm.setter('current'), (sm, 'whatever'))
конечно, это не очень сексуально, поэтому kv часто является более чистым решением для этих вещей, но он должен работать.
PS: в случае, если вы не знаете об этом!--2--> происходит от functools
module, и часто полезно создавать такие обратные вызовы с предварительно загруженным параметром.