2017-02-19 19 views
1

Я борюсь с картой Kivy в течение некоторого времени. Я не могу найти ответ на мою проблему в Интернете.Переменная функции перехода на метку

У меня есть два файла: main.py и .kv. В файле main.py у меня есть функция внутри Boxlayout.

Например:

class Box(BoxLayout): 

    def change(self): 
      variable = 0 

      while variable < 10: 
       text = "Some text " + str(variable) 
       variable += 1 

Как вы можете видеть, есть строковая переменная «текст» и эта переменная отличается на каждом цикле.

Теперь в .kv файле У меня есть ярлык. Например:

Box: 
    BoxLayout: 
     Button: 
      id: butt 
      text: "" 
      on_press: root.change() 
     Label: 
      id: label_text 

Я хотел бы кнопку, чтобы запустить функцию изменения(), и я хотел бы видеть значение «текст» переменной отображается в метке. Итак, после нажатия кнопки на кнопке он увидит изменение текста на ярлыке: «Some text 0», «Some text 1», «Some text 2» .... «Some text 9».

Я пытался использовать метки ID в main.py файл как:

(внутри изменение функции)

label = self.ids['label_text'] 
self.count = str(variable) 
label.text = "Some text " + self.count 

, но в конечном итоге ни с чем. Я думаю, что мог бы сделать это с помощью «возвращаемого текста» в конце функции, но я не хочу передавать только последнюю «текстовую» переменную из цикла. Я хочу, чтобы метка меняла текст при изменении переменных во время цикла.

Прошу совета!

ответ

0

from kivy.properties import StringProperty и определить текст вашего ярлыка как label_text = StringProperty(), поэтому он будет обновлен в графическом интерфейсе, если он изменен в вашей логике. в файле .kv добавить text: root.label_text к Label свойств и в файле .py:

class Box(BoxLayout): 
    label_text = StringProperty() 

    def change(self): 
      variable = 0 
      while variable < 10: 
       self.label_text = "Some text " + str(variable) 
       variable += 1 

это ответ на ваш вопрос об обновлении текстового значения лейбла в графическом интерфейсе. Но не используйте такие петли, как while True или тот, который вы использовали в коде, потому что он остановит поток графического интерфейса kivy от самого обновления. Вместо этого используйте kivy Clock (from kivy.clock import Clock), чтобы запланировать задачу и запустить ее через определенные промежутки времени, чтобы поток GUI не был заблокирован. Что-то вроде

class Box(BoxLayout): 

    label_text = StringProperty() 
    interval = 0.5 # Second 
    offset = 0 

    def change(self): 
     # You ask the clock to update the label's value every self.interval (0.5) second 
     self.event = Clock.schedule_interval(self.update_label_text, self.interval) 

    def update_label_text(self, dt): 
     if self.offset < 10: 
      self.label_text = "some_text" + str(self.offset) 
      self.offset += 1 
     else: 
      # Finally ask the clock to forget about updating 
      Clock.unschedule(self.event) 
+0

спасибо. Это решило мою проблему, но ... мне все равно не на 100% понятно, как это работает. Можете ли вы порекомендовать хороший учебник по киви? – Maciejjy

+0

@Maciejjy Было бы неплохо принять и проголосовать за ответ, если он работает :) Вы взяли это? https://kivy.org/docs/tutorials/pong.html – Juggernaut

+0

Конечно. Но я не могу проголосовать. Получил сообщение о том, что для пользователя с менее чем 15 репутацией не изменяйте счет сообщения. – Maciejjy

0

По-прежнему возникают проблемы с отображением текста в ярлыке. При коротких функциях, кажется, все хорошо, но у меня есть эта функция с большим количеством открытия файлов, IFS и записи в базу данных:

def add_to_base(self, dt): 
    self.adding = "Adding to database..." 
    with open("new_links.txt", "r", encoding='utf-8') as f: 
     for line in f: 
      working on html here 
      xxx = got list of string here 
      for x in xxx: 
       if .... 
        zzz = got another list with string 
      for i in xxx: 
       if 
       . 
       . 
       Lots of elif's 
      write element to database 
      print("Added to databes") 
      if element is last element: 
       Clock.unschedule(self.event) 

Конечно, это не фактический код, просто модель, как она работает. Я хотел бы отображать и обновлять текст «self.adding» из этой функции. В .kv файле У меня есть надпись с текстом: self.adding. В запустить эту функцию add_to_base с:

def update_base(self): 
    self.event = Clock.schedule_interval(self.add_to_base, self.interval) 

Проблема в том, что текст отображается на этикетке, но в самом конце этой функции.Эта функция занимает много времени, чтобы закончить (около 15 минут, чтобы пройти через элементы и добавить их в базу данных), и когда функция закончена, отображается текст. Я бы хотел показать этот текст в самом начале.

+0

Функция 'add_to_base()' блокирует поток графического интерфейса kivy, пока это не будет выполнено. Как я уже сказал, избегайте запуска таких циклов с помощью 'for' и' while' и используйте kivy Clock, чтобы запланировать их для вас. Я предлагаю добавить все строки вашего файла в 'Queue()', а затем запланировать интервал для чтения из этого 'Queue()' и работать на нем, а не тот, который вы сделали, блокируя поток GUI. читать о python 'Queue()' – Juggernaut

+0

О, хорошо. Итак, если у нас очень долго заканчивается (например, 15 минут), тогда kivy.Clock не может обновлять любую переменную из этой функции быстрее, чем каждые 15 минут? Интервал в этом случае не важен, потому что он меньше времени функции? – Maciejjy

+0

как-то, я имею в виду разбить задачу на более мелкие задачи и задавать часы каждой задаче интервалами. – Juggernaut