Взаимодействие между виджетами Kivy в Python

#python #kivy #kivy-language

#python #флажок #kivy

Вопрос:

Я делаю проект с использованием kivy, но у меня проблема с флажками. Сначала я пытаюсь выполнить программу, подобную кодированию на python (я знаю, что это не чисто, но я понимаю больше) И у меня есть первый экран с этой кодировкой:

 from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.checkbox import CheckBox




class MainScreen(GridLayout):
    def __init__(self,**kwargs):
        e=[]
        super(MainScreen, self).__init__(**kwargs)
        self.cols=2
        def on_checkbox_active(checkbox, value):
            if value:
                e.append(value)
                print e
            else:
                print('The checkbox', checkbox, 'is inactive')

        self.add_widget(Label(text='Inserta assignatures desitjades',font_size=35))
        self.add_widget(Label(text=''))
        ch1 = CheckBox()
        self.add_widget(ch1)
        self.add_widget(Label(text='Termotecnia'))
        ch2 = CheckBox()
        self.add_widget(ch2)
        self.add_widget(Label(text='Termotecnia'))
        ch3 = CheckBox()
        self.add_widget(ch3)
        self.add_widget(Label(text='Termotecnia'))
        ch4 = CheckBox()
        self.add_widget(ch4)
        self.add_widget(Label(text='Termotecnia'))
        b1=Button(text='Exit',background_color=[0.7,0.7,1,1],font_size=24)  
        self.add_widget(b1)
        b2=Button(text='Next',font_size=24,font_color=[1,3,4,0],background_color=[1,2,3,6]) 
        self.add_widget(b2)
        ch1.bind(active=on_checkbox_active)
        ch2.bind(active=on_checkbox_active)
        b1.bind(on_press=exit)
        b2.bind(on_press=reloaded)
...

class SimpleKivy(App):
    def build(self):
        return MainScreen()


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

Я хочу, например, выбрать два или три варианта и сохранить их для следующего экрана, как тип выбора. Если кто-нибудь знает, как это сделать и сохранить информацию для следующего экрана, это мне очень поможет, потому что у меня есть код следующего экрана для всех опций, но я хочу предварительно выбрать на первом экране, а затем использовать только то, что я выбрал. Также, если кто-нибудь может мне помочь, я хочу знать, как выполнить переход в другой класс (экран) при нажатии кнопки «Далее». Я знаю, что этот вопрос довольно прост, но я новичок в программировании kivy, и некоторые концепции довольно сложны. Спасибо.

Ответ №1:

То, что вы хотите, — это доступ к переменным в других классах. Иногда это может раздражать, и вы можете сделать это либо сложным способом со всеми __init__() и прочим, либо … появляется более простой способ: это get_running_app() .

Вы можете создать словарь или что-то еще, где вы можете хранить любое значение, к которому должны обращаться другие классы. Это похоже на использование globals , и это стоит вам меньше строк кода. Например, в вашем случае вы могли бы использовать словарь (или вложенные словари, json, …) для хранения, например 'checkboxes':'<names of checked ones>' , и в каждом инициализации вы можете перебирать эти значения, чтобы устанавливать флажки active

По сути, все, что вам нужно, это a = App.get_running_app() где-то и что-то для доступа в main — App — class.

Пример:

 from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
Builder.load_string('''
<Root>:
    MainScreen:
        name: 'main'
    AnotherScreen:
        name: 'another'
<MainScreen>:
    BoxLayout:
        Button:
            text: 'next screen'
            on_release: root.parent.current='another'
        Button:
            text: 'ping!'
            on_release: root.ping()
<AnotherScreen>:
    BoxLayout:
        Button:
            text: 'previous screen'
            on_release: root.parent.current='main'
        Button:
            text: 'ping!'
            on_release: root.ping()
''')

class MainScreen(Screen):
    def __init__(self, **kw):
        super(MainScreen, self).__init__(**kw)
        self.a = App.get_running_app()
    def ping(self):
        print self.a.big_dict['hi']

class AnotherScreen(Screen):
    def ping(self):
        b = App.get_running_app()
        print b.big_dict['hi']

class Root(ScreenManager):
    pass
class SimpleKivy(App):
    big_dict={'hi':'hi there!'}
    def build(self):
        return Root()
SimpleKivy().run()
  

Вы можете видеть, что нет необходимости вызывать __init__() , нет необходимости писать больше строк кода, если вам действительно не нужно.

Комментарии:

1. Но как это было бы? У меня есть идея, но я не знаю, как сохранить информацию, потому что мне нужно знать последнее состояние каждого флажка. Если у меня 5 флажков, а 1 не выбран, как я могу сохранить эту информацию в словаре?

2. Создайте функцию, которая будет запускаться при каждом изменении экрана. Либо сохраняйте идентификаторы флажков где-либо, либо перебирайте каждого дочернего элемента класса (проверяя, является ли это флажком) и сохраняйте его состояние в словаре. Либо вы можете сохранить его в том порядке, в котором виджеты были добавлены в класс (при условии, что у вас одинаковое количество флажков), либо здесь можно указать идентификаторы. Например {<chbox's id>:<state>} , или вложенный {'chboxes':{<chbox's id>:<state>}} .

3. Хорошо, спасибо. Я сделал все, что вы сказали, и это работает. Теперь я хотел бы создать следующий экран на основе выбора главного экрана, например, функции. Например, если я установлю первый флажок и последний, на следующем экране будет ввод текста для первого и последнего. Как я могу создать программу, которая может автоматически добавлять виджеты на основе выбора предыдущего экрана? Извините, если я спрашиваю слишком много, я очень заинтересован в kivy, но я не слишком много знаю. Спасибо.

4. Ну, создайте базовую структуру экрана и используйте __init__() для создания вашего контента изнутри. Я не совсем уверен, вызывается ли init при вызове add_widget(your_screen) , но если нет, то вам нужно будет вызвать его вручную после add_widget() . В классе вы могли бы, например, задать список [0,0,0,0] , который вы бы обновили с помощью init для [1,0,0,1] получения значений из словаря, где у вас уже есть состояния флажков. Затем вы должны перебрать список и для каждого 1 добавить TextInput флажок вместо (если вы хотите создать один и тот же экран с заменой только двух флажков).

5. Хорошо, я открою еще один вопрос, потому что я пытался добавить еще один экран, но он не может работать как GridLayout, только как screen. Я могу выполнить итерацию на языке python, но я не знаю, как это сделать на языке kivy. Я приведу здесь код моей программы на тот момент. Большое спасибо.